Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

upstream of transparanty kms logger #195

Merged
merged 2 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ ccf-app/
nohup.out
aad.env
*.log
temp*/
__pycache__/
104 changes: 52 additions & 52 deletions governance/constitution/kms_actions.js

Large diffs are not rendered by default.

25 changes: 17 additions & 8 deletions src/attestation/AttestationValidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,27 @@ import {
} from "@microsoft/ccf-app/global";
import { SnpAttestationClaims } from "./SnpAttestationClaims";
import { keyReleasePolicyMap } from "../repositories/Maps";
import { Logger } from "../utils/Logger";
import { Logger, LogContext } from "../utils/Logger";
import { KeyReleasePolicy } from "../policies/KeyReleasePolicy";

// Validate the attestation by means of the key release policy
export const validateAttestation = (
attestation: ISnpAttestation,
): ServiceResult<string | IAttestationReport> => {
Logger.debug(`Start attestation validation`);
const logContext = new LogContext().appendScope("validateAttestation");
Logger.debug(`Start attestation validation`, logContext);
if (!attestation) {
return ServiceResult.Failed<string>(
{ errorMessage: "missing attestation" },
400,
logContext
);
}
if (!attestation.evidence && typeof attestation.evidence !== "string") {
return ServiceResult.Failed<string>(
{ errorMessage: "missing or bad attestation.evidence" },
400,
logContext
);
}
if (
Expand All @@ -39,6 +42,7 @@ export const validateAttestation = (
return ServiceResult.Failed<string>(
{ errorMessage: "missing or bad attestation.evidence" },
400,
logContext
);
}
if (
Expand All @@ -48,6 +52,7 @@ export const validateAttestation = (
return ServiceResult.Failed<string>(
{ errorMessage: "missing or bad attestation.uvm_endorsements" },
400,
logContext
);
}
if (
Expand All @@ -57,6 +62,7 @@ export const validateAttestation = (
return ServiceResult.Failed<string>(
{ errorMessage: "missing or bad attestation.endorsed_tcb" },
400,
logContext
);
}
let evidence: ArrayBuffer;
Expand All @@ -71,6 +77,7 @@ export const validateAttestation = (
return ServiceResult.Failed<string>(
{ errorMessage: "Malformed attestation.evidence" },
400,
logContext
);
}
try {
Expand All @@ -81,6 +88,7 @@ export const validateAttestation = (
return ServiceResult.Failed<string>(
{ errorMessage: "Malformed attestation.endorsements" },
400,
logContext
);
}
try {
Expand All @@ -91,6 +99,7 @@ export const validateAttestation = (
return ServiceResult.Failed<string>(
{ errorMessage: "Malformed attestation.uvm_endorsements" },
400,
logContext
);
}
try {
Expand All @@ -104,14 +113,14 @@ export const validateAttestation = (
endorsed_tcb,
);
Logger.debug(
`Attestation validation report: ${JSON.stringify(attestationReport)}`,
`Attestation validation report: ${JSON.stringify(attestationReport)}`, logContext
);

const claimsProvider = new SnpAttestationClaims(attestationReport);
const attestationClaims = claimsProvider.getClaims();
Logger.debug(`Attestation claims: `, attestationClaims);
Logger.debug(`Attestation claims: `, logContext, attestationClaims);
Logger.debug(
`Report Data: `,
`Report Data: `, logContext,
attestationClaims["x-ms-sevsnpvm-reportdata"],
);

Expand All @@ -121,9 +130,8 @@ export const validateAttestation = (
Logger.debug(
`Key release policy: ${JSON.stringify(
keyReleasePolicy,
)}, keys: ${Object.keys(keyReleasePolicy)}, keys: ${
Object.keys(keyReleasePolicy).length
}`,
)}, keys: ${Object.keys(keyReleasePolicy)}, keys: ${Object.keys(keyReleasePolicy).length
}`, logContext
);

const policyValidationResult = KeyReleasePolicy.validateKeyReleasePolicy(
Expand All @@ -135,6 +143,7 @@ export const validateAttestation = (
return ServiceResult.Failed<string>(
{ errorMessage: `Internal error: ${exception.message}` },
500,
logContext
);
}
};
17 changes: 10 additions & 7 deletions src/authorization/AuthenticationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { JwtValidator } from "./jwt/JwtValidator";
import { IValidatorService } from "./IValidationService";
import { UserCertValidator } from "./certs/UserCertValidator";
import { MemberCertValidator } from "./certs/MemberCertValidator";
import { Logger } from "../utils/Logger";
import { Logger, LogContext } from "../utils/Logger";

/**
* CCF authentication policies
Expand All @@ -29,16 +29,18 @@ export class AuthenticationService implements IAuthenticationService {
CcfAuthenticationPolicyEnum,
IValidatorService
>();
private logContext: LogContext;

constructor() {
constructor(logContext?: LogContext) {
this.logContext = (logContext?.clone() || new LogContext()).appendScope("AuthenticationService");
this.validators.set(CcfAuthenticationPolicyEnum.Jwt, new JwtValidator());
this.validators.set(
CcfAuthenticationPolicyEnum.User_cert,
new UserCertValidator(),
new UserCertValidator(this.logContext),
);
this.validators.set(
CcfAuthenticationPolicyEnum.Member_cert,
new MemberCertValidator(),
new MemberCertValidator(this.logContext),
);
}

Expand All @@ -53,10 +55,11 @@ export class AuthenticationService implements IAuthenticationService {
const caller = request.caller as unknown as ccfapp.AuthnIdentityCommon;
if (!caller) {
// no caller policy
return [caller, ServiceResult.Succeeded("")];
return [caller, ServiceResult.Succeeded("", undefined, this.logContext)];
}
Logger.debug(
`Authorization: isAuthenticated result (AuthenticationService)-> ${caller.policy},${JSON.stringify(caller)}`,
this.logContext
);
const validator = this.validators.get(
<CcfAuthenticationPolicyEnum>caller.policy,
Expand All @@ -68,7 +71,7 @@ export class AuthenticationService implements IAuthenticationService {
ServiceResult.Failed({
errorMessage: `Error: invalid caller identity (AuthenticationService)-> ${caller.policy}`,
errorType: "AuthenticationError",
}),
}, 400, this.logContext),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need 400 (auth error) here while we already have errorType: "AuthenticationError",. Looks like they are duplicated information?

I'm sure I'm missing something here but also I think using self-defined "AuthenticationError" type (i.e. what we have already) is nicer approach than using http specific code in general. That gives us better flexibility if necessary.

];
}

Expand All @@ -79,7 +82,7 @@ export class AuthenticationService implements IAuthenticationService {
ServiceResult.Failed({
errorMessage: `Error: invalid caller identity (AuthenticationService)-> ${ex}`,
errorType: "AuthenticationError",
}),
}, 400, this.logContext),
];
}
}
Expand Down
15 changes: 11 additions & 4 deletions src/authorization/certs/MemberCertValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ccf } from "@microsoft/ccf-app/global";
import { IValidatorService } from "../IValidationService";
import { ServiceResult } from "../../utils/ServiceResult";
import { UserMemberAuthnIdentity } from "./UserCertValidator";
import { LogContext } from "../../utils/Logger";

/**
* CCF member information
Expand All @@ -16,17 +17,23 @@ interface CCFMember {
}

export class MemberCertValidator implements IValidatorService {
private logContext: LogContext;

constructor(logContext?: LogContext) {
this.logContext = (logContext?.clone() || new LogContext()).appendScope("MemberCertValidator");
}

validate(request: ccfapp.Request<any>): ServiceResult<string> {
const memberCaller = request.caller as unknown as UserMemberAuthnIdentity;
const identityId = memberCaller.id;
const isValid = this.isActiveMember(identityId);
if (isValid.success && isValid.body) {
return ServiceResult.Succeeded(identityId);
return ServiceResult.Succeeded(identityId, undefined, this.logContext);
}
return ServiceResult.Failed({
errorMessage: `Error: invalid caller identity (MemberCertValidator)->${JSON.stringify(isValid)}`,
errorType: "AuthenticationError",
});
}, 400, this.logContext);
}

/**
Expand Down Expand Up @@ -54,12 +61,12 @@ export class MemberCertValidator implements IValidatorService {
if (memberInfoBuf !== undefined) {
const memberInfo = ccf.bufToJsonCompatible(memberInfoBuf) as CCFMember;
const isActiveMember = memberInfo && memberInfo.status === "Active";
return ServiceResult.Succeeded(isActiveMember && isMember);
return ServiceResult.Succeeded(isActiveMember && isMember, undefined, this.logContext);
} else {
// memberInfoBuf is undefined
return ServiceResult.Failed({
errorMessage: "Member information is undefined.",
});
}, 400, this.logContext);
}
}
}
13 changes: 10 additions & 3 deletions src/authorization/certs/UserCertValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as ccfapp from "@microsoft/ccf-app";
import { ccf } from "@microsoft/ccf-app/global";
import { IValidatorService } from "../IValidationService";
import { ServiceResult } from "../../utils/ServiceResult";
import { LogContext } from "../../utils/Logger";

/**
* CCF user and member authentication identity
Expand All @@ -31,17 +32,23 @@ export interface UserMemberAuthnIdentity extends ccfapp.AuthnIdentityCommon {
}

export class UserCertValidator implements IValidatorService {
private logContext: LogContext;

constructor(logContext?: LogContext) {
this.logContext = (logContext?.clone() || new LogContext()).appendScope("UserCertValidator");
}

validate(request: ccfapp.Request<any>): ServiceResult<string> {
const userCaller = request.caller as unknown as UserMemberAuthnIdentity;
const identityId = userCaller.id;
const isValid = this.isUser(identityId);
if (isValid.success && isValid.body) {
return ServiceResult.Succeeded(identityId);
return ServiceResult.Succeeded(identityId, undefined, this.logContext);
}
return ServiceResult.Failed({
errorMessage: `Error: invalid caller identity (UserCertValidator)->${JSON.stringify(isValid)}`,
errorType: "AuthenticationError",
});
}, 400, this.logContext);
}

/**
Expand All @@ -57,6 +64,6 @@ export class UserCertValidator implements IValidatorService {
ccfapp.arrayBuffer,
);
const result = usersCerts.has(ccf.strToBuf(userId));
return ServiceResult.Succeeded(result);
return ServiceResult.Succeeded(result, undefined, this.logContext);
}
}
9 changes: 5 additions & 4 deletions src/authorization/jwt/DemoJwtProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import * as ccfapp from "@microsoft/ccf-app";
import { ServiceResult } from "../../utils/ServiceResult";
import { IJwtIdentityProvider } from "./IJwtIdentityProvider";
import { authorizeJwt } from "./MsJwtProvider";
import { Logger } from "../../utils/Logger";
import { Logger, LogContext } from "../../utils/Logger";

const errorType = "AuthenticationError";

export class DemoJwtProvider implements IJwtIdentityProvider {
constructor(public name: string) {}
private static readonly logContext = new LogContext().appendScope("DemoJwtProvider");

/**
* Check if caller's access token is valid
Expand All @@ -25,7 +26,7 @@ export class DemoJwtProvider implements IJwtIdentityProvider {
return ServiceResult.Failed({
errorMessage: "The JWT has no valid iss",
errorType,
});
}, 400, DemoJwtProvider.logContext);
}

const isAuthorized = authorizeJwt(issuer, identity);
Expand All @@ -34,7 +35,7 @@ export class DemoJwtProvider implements IJwtIdentityProvider {
}

const identityId = identity?.jwt?.payload?.sub;
Logger.debug(`JWT validation succeeded: ${identityId}`);
return ServiceResult.Succeeded(identityId);
Logger.debug(`JWT validation succeeded: ${identityId}`, DemoJwtProvider.logContext);
return ServiceResult.Succeeded(identityId, undefined, DemoJwtProvider.logContext);
}
}
13 changes: 7 additions & 6 deletions src/authorization/jwt/JwtValidationPolicyMap.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
import { ccf } from "@microsoft/ccf-app/global";
import { Logger } from "../../utils/Logger";
import { Logger, LogContext } from "../../utils/Logger";

const validationPolicyMapName = "public:ccf.gov.policies.jwt_validation";

export class JwtValidationPolicyMap {
public static read(issuer: string): { [key: string]: string } | undefined {
public static read(issuer: string, logContextIn? : LogContext): { [key: string]: string } | undefined {
const logContext = (logContextIn?.clone() || new LogContext()).appendScope("JwtValidationPolicyMap");
// For testing list all issuers
const issuersMap = ccf.kv["public:ccf.gov.jwt.issuers"];
issuersMap.forEach((v, k) => {
let issuer = ccf.bufToStr(k);
let info = ccf.bufToJsonCompatible(v);
Logger.debug(`Issuer: ${issuer}: ${JSON.stringify(info)}`);
Logger.debug(`Issuer: ${issuer}: ${JSON.stringify(info)}`, logContext);
});

const keyBuf = ccf.strToBuf(issuer);
if (!ccf.kv[validationPolicyMapName].has(keyBuf)) {
Logger.error(`No JWT validation Policy for issuer: ${issuer}`);
Logger.error(`No JWT validation Policy for issuer: ${issuer}`, logContext);
return undefined;
}

const policyBuf = ccf.kv[validationPolicyMapName].get(keyBuf);
if (policyBuf === undefined) {
Logger.error(`Policy buffer is undefined for issuer: ${issuer}`);
Logger.error(`Policy buffer is undefined for issuer: ${issuer}`, logContext);
return undefined;
}

const policy = ccf.bufToStr(policyBuf);
Logger.info(`JWT validation: Policy: ${policy} for issuer: ${issuer}`);
Logger.info(`JWT validation: Policy: ${policy} for issuer: ${issuer}`, logContext);
return JSON.parse(policy);
}
}
Loading