@msn-control/liftoff 0.9.9 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DEVELOPER.md +142 -0
- package/README.md +26 -18
- package/assets/governance/single-maintainer-gitflow/policy.md +13 -11
- package/dist/args.js +23 -1
- package/dist/args.js.map +1 -1
- package/dist/artifact-lifecycle.d.ts +1 -1
- package/dist/artifact-lifecycle.js +5 -0
- package/dist/artifact-lifecycle.js.map +1 -1
- package/dist/catalogs.d.ts +2 -0
- package/dist/catalogs.js +13 -1
- package/dist/catalogs.js.map +1 -1
- package/dist/commands.js +365 -17
- package/dist/commands.js.map +1 -1
- package/dist/file-system.js +100 -13
- package/dist/file-system.js.map +1 -1
- package/dist/governance-activation/activation-state.d.ts +32 -0
- package/dist/governance-activation/activation-state.js +165 -0
- package/dist/governance-activation/activation-state.js.map +1 -0
- package/dist/governance-activation/approvals.d.ts +188 -0
- package/dist/governance-activation/approvals.js +508 -0
- package/dist/governance-activation/approvals.js.map +1 -0
- package/dist/governance-activation/canonical-json.d.ts +3 -0
- package/dist/governance-activation/canonical-json.js +36 -0
- package/dist/governance-activation/canonical-json.js.map +1 -0
- package/dist/governance-activation/commands.d.ts +10 -0
- package/dist/governance-activation/commands.js +1023 -0
- package/dist/governance-activation/commands.js.map +1 -0
- package/dist/governance-activation/compatibility.d.ts +68 -0
- package/dist/governance-activation/compatibility.js +447 -0
- package/dist/governance-activation/compatibility.js.map +1 -0
- package/dist/governance-activation/credentials.d.ts +160 -0
- package/dist/governance-activation/credentials.js +403 -0
- package/dist/governance-activation/credentials.js.map +1 -0
- package/dist/governance-activation/doctor.d.ts +10 -0
- package/dist/governance-activation/doctor.js +379 -0
- package/dist/governance-activation/doctor.js.map +1 -0
- package/dist/governance-activation/evidence.d.ts +49 -0
- package/dist/governance-activation/evidence.js +246 -0
- package/dist/governance-activation/evidence.js.map +1 -0
- package/dist/governance-activation/graph.d.ts +397 -0
- package/dist/governance-activation/graph.js +441 -0
- package/dist/governance-activation/graph.js.map +1 -0
- package/dist/governance-activation/identity.d.ts +35 -0
- package/dist/governance-activation/identity.js +89 -0
- package/dist/governance-activation/identity.js.map +1 -0
- package/dist/governance-activation/index.d.ts +18 -0
- package/dist/governance-activation/index.js +19 -0
- package/dist/governance-activation/index.js.map +1 -0
- package/dist/governance-activation/migration.d.ts +44 -0
- package/dist/governance-activation/migration.js +268 -0
- package/dist/governance-activation/migration.js.map +1 -0
- package/dist/governance-activation/readiness.d.ts +23 -0
- package/dist/governance-activation/readiness.js +158 -0
- package/dist/governance-activation/readiness.js.map +1 -0
- package/dist/governance-activation/reconciliation.d.ts +11 -0
- package/dist/governance-activation/reconciliation.js +58 -0
- package/dist/governance-activation/reconciliation.js.map +1 -0
- package/dist/governance-activation/release-integrity.d.ts +11 -0
- package/dist/governance-activation/release-integrity.js +49 -0
- package/dist/governance-activation/release-integrity.js.map +1 -0
- package/dist/governance-activation/seed-lifecycle.d.ts +116 -0
- package/dist/governance-activation/seed-lifecycle.js +609 -0
- package/dist/governance-activation/seed-lifecycle.js.map +1 -0
- package/dist/governance-activation/source-of-truth.d.ts +164 -0
- package/dist/governance-activation/source-of-truth.js +986 -0
- package/dist/governance-activation/source-of-truth.js.map +1 -0
- package/dist/governance-activation/task-projection.d.ts +21 -0
- package/dist/governance-activation/task-projection.js +75 -0
- package/dist/governance-activation/task-projection.js.map +1 -0
- package/dist/governance-activation/transitions.d.ts +163 -0
- package/dist/governance-activation/transitions.js +2128 -0
- package/dist/governance-activation/transitions.js.map +1 -0
- package/dist/governance-activation/type-contract.d.ts +1 -0
- package/dist/governance-activation/type-contract.js +27 -0
- package/dist/governance-activation/type-contract.js.map +1 -0
- package/dist/governance-activation/types.d.ts +390 -0
- package/dist/governance-activation/types.js +108 -0
- package/dist/governance-activation/types.js.map +1 -0
- package/dist/governance-activation/validators.d.ts +17 -0
- package/dist/governance-activation/validators.js +1305 -0
- package/dist/governance-activation/validators.js.map +1 -0
- package/dist/init-filesystem.js +5 -1
- package/dist/init-filesystem.js.map +1 -1
- package/dist/interactive.js +4 -3
- package/dist/interactive.js.map +1 -1
- package/dist/planner.js +5 -5
- package/dist/planner.js.map +1 -1
- package/dist/power-apps-templates.js +14 -1
- package/dist/power-apps-templates.js.map +1 -1
- package/dist/process-runner.d.ts +3 -0
- package/dist/process-runner.js +68 -10
- package/dist/process-runner.js.map +1 -1
- package/dist/repository-governance.d.ts +13 -3
- package/dist/repository-governance.js +357 -51
- package/dist/repository-governance.js.map +1 -1
- package/dist/telemetry/contract.d.ts +1 -1
- package/dist/telemetry/contract.js +6 -0
- package/dist/telemetry/contract.js.map +1 -1
- package/dist/templates.js +320 -25
- package/dist/templates.js.map +1 -1
- package/dist/types.d.ts +15 -7
- package/docs/cli-reference.md +61 -13
- package/docs/configuration-and-manifests.md +43 -16
- package/docs/existing-repositories.md +22 -11
- package/docs/getting-started.md +46 -10
- package/docs/project-structure.md +35 -6
- package/docs/repository-governance.md +200 -245
- package/docs/safety-and-consent.md +24 -2
- package/docs/troubleshooting.md +59 -4
- package/docs/workloads.md +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { type CommandResult, type CommandRunner } from '../process-runner.js';
|
|
2
|
+
import type { ExternalCommand } from '../types.js';
|
|
3
|
+
import type { ActivationIdentity, CredentialPermissionSet, CredentialPolicy, CredentialPolicyProofMetadata, CredentialRepositoryIdentity, CredentialWorkflowAllowlistEntry } from './types.js';
|
|
4
|
+
import { runnerPreflightDisplayNameTemplate, runnerPreflightPatLifetimeDays, runnerPreflightRotationLeadDays, runnerPreflightSecretName } from './types.js';
|
|
5
|
+
export declare const credentialPolicyPathParts: readonly ['governance', 'credentials', 'preflight-policy.json'];
|
|
6
|
+
export interface CredentialRepositoryInput {
|
|
7
|
+
id?: string;
|
|
8
|
+
owner: string;
|
|
9
|
+
name: string;
|
|
10
|
+
}
|
|
11
|
+
export interface RepositorySecretReadback {
|
|
12
|
+
repository: CredentialRepositoryIdentity;
|
|
13
|
+
secretName: typeof runnerPreflightSecretName;
|
|
14
|
+
updatedAt: string;
|
|
15
|
+
readbackDigest: string;
|
|
16
|
+
}
|
|
17
|
+
export interface RepositorySecretWriteRequest {
|
|
18
|
+
repository: CredentialRepositoryIdentity;
|
|
19
|
+
secretName: typeof runnerPreflightSecretName;
|
|
20
|
+
value: SensitiveCredentialValue;
|
|
21
|
+
}
|
|
22
|
+
export interface DiscoveredGitHubAppInstallation {
|
|
23
|
+
installationId: number;
|
|
24
|
+
appSlug: string;
|
|
25
|
+
approved: boolean;
|
|
26
|
+
verified: boolean;
|
|
27
|
+
selection: 'selected-repository' | 'all-repositories';
|
|
28
|
+
repositories: readonly CredentialRepositoryIdentity[];
|
|
29
|
+
permissions: CredentialPermissionSet;
|
|
30
|
+
permissionsVerifiedAt: string;
|
|
31
|
+
readbackDigest?: string;
|
|
32
|
+
token: {
|
|
33
|
+
canGenerate: boolean;
|
|
34
|
+
ttlSeconds: number;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export interface GitHubCredentialAdapter {
|
|
38
|
+
discoverAppInstallations(repository: CredentialRepositoryIdentity): Promise<readonly DiscoveredGitHubAppInstallation[]>;
|
|
39
|
+
readRepositorySecret(repository: CredentialRepositoryIdentity, secretName: typeof runnerPreflightSecretName): Promise<RepositorySecretReadback | null>;
|
|
40
|
+
setRepositorySecret?(request: RepositorySecretWriteRequest): Promise<RepositorySecretReadback>;
|
|
41
|
+
}
|
|
42
|
+
export interface PatEnrollmentGuidance {
|
|
43
|
+
authKind: 'fine-grained-pat';
|
|
44
|
+
displayNameTemplate: typeof runnerPreflightDisplayNameTemplate;
|
|
45
|
+
displayName: string;
|
|
46
|
+
secretName: typeof runnerPreflightSecretName;
|
|
47
|
+
lifetimeDays: typeof runnerPreflightPatLifetimeDays;
|
|
48
|
+
owner: string;
|
|
49
|
+
repository: CredentialRepositoryIdentity;
|
|
50
|
+
selectedRepositoryOnly: true;
|
|
51
|
+
permissions: CredentialPermissionSet;
|
|
52
|
+
writes: readonly [];
|
|
53
|
+
expiresAt: string;
|
|
54
|
+
rotationLeadDays: typeof runnerPreflightRotationLeadDays;
|
|
55
|
+
rotationDueAt: string;
|
|
56
|
+
}
|
|
57
|
+
export type CredentialPlan = {
|
|
58
|
+
authKind: 'github-app';
|
|
59
|
+
policy: CredentialPolicy;
|
|
60
|
+
app: DiscoveredGitHubAppInstallation;
|
|
61
|
+
fallbackGuidance: null;
|
|
62
|
+
rejectionReasons: readonly string[];
|
|
63
|
+
} | {
|
|
64
|
+
authKind: 'fine-grained-pat';
|
|
65
|
+
policy: null;
|
|
66
|
+
app: null;
|
|
67
|
+
fallbackGuidance: PatEnrollmentGuidance;
|
|
68
|
+
rejectionReasons: readonly string[];
|
|
69
|
+
};
|
|
70
|
+
export interface CredentialUsageReference {
|
|
71
|
+
workflowPath: string;
|
|
72
|
+
job: string;
|
|
73
|
+
}
|
|
74
|
+
export interface CredentialPolicyUsage {
|
|
75
|
+
repository: CredentialRepositoryIdentity;
|
|
76
|
+
permissions: CredentialPermissionSet;
|
|
77
|
+
references: readonly CredentialUsageReference[];
|
|
78
|
+
forwardsCredential: boolean;
|
|
79
|
+
verifiedReadbackDigest?: string;
|
|
80
|
+
now?: Date;
|
|
81
|
+
}
|
|
82
|
+
export interface CredentialPolicyUsageResult {
|
|
83
|
+
ready: boolean;
|
|
84
|
+
status: CredentialPolicy['status'] | 'not-ready';
|
|
85
|
+
issues: readonly string[];
|
|
86
|
+
}
|
|
87
|
+
export interface CredentialLeakInput {
|
|
88
|
+
source: 'generated-artifact' | 'process-log' | 'imported-evidence' | 'screenshot-text' | 'chat-text';
|
|
89
|
+
label: string;
|
|
90
|
+
text: string;
|
|
91
|
+
}
|
|
92
|
+
export interface CredentialLeakScanResult {
|
|
93
|
+
status: 'clear' | 'compromised';
|
|
94
|
+
leaks: readonly {
|
|
95
|
+
source: CredentialLeakInput['source'];
|
|
96
|
+
label: string;
|
|
97
|
+
pattern: string;
|
|
98
|
+
}[];
|
|
99
|
+
guidance: readonly string[];
|
|
100
|
+
unauthorizedRevocationAttempted: false;
|
|
101
|
+
}
|
|
102
|
+
export type MaskedCredentialPrompt = (message: string) => Promise<SensitiveCredentialValue>;
|
|
103
|
+
export interface GitHubCliSecretWriteResult {
|
|
104
|
+
command: ExternalCommand;
|
|
105
|
+
result: CommandResult;
|
|
106
|
+
}
|
|
107
|
+
export declare class SensitiveCredentialValue {
|
|
108
|
+
#private;
|
|
109
|
+
private constructor();
|
|
110
|
+
static fromMaskedInput(value: string): SensitiveCredentialValue;
|
|
111
|
+
use<T>(consumer: (value: string) => T): T;
|
|
112
|
+
release(): void;
|
|
113
|
+
}
|
|
114
|
+
export declare function inquirerMaskedCredentialPrompt(message: string): Promise<SensitiveCredentialValue>;
|
|
115
|
+
export declare function repositorySecretSetCommand(repository: CredentialRepositoryIdentity, secretName: typeof runnerPreflightSecretName): ExternalCommand;
|
|
116
|
+
export declare function writeRepositorySecretWithGitHubCli(input: {
|
|
117
|
+
runner: CommandRunner;
|
|
118
|
+
repository: CredentialRepositoryIdentity;
|
|
119
|
+
secretName: typeof runnerPreflightSecretName;
|
|
120
|
+
value: SensitiveCredentialValue;
|
|
121
|
+
cwd?: string;
|
|
122
|
+
}): Promise<GitHubCliSecretWriteResult>;
|
|
123
|
+
export declare function canonicalCredentialRepository(input: CredentialRepositoryInput): CredentialRepositoryIdentity;
|
|
124
|
+
export declare function repositoryNameFromFullName(fullName: string): string;
|
|
125
|
+
export declare function runnerPreflightDisplayName(repositoryName: string): string;
|
|
126
|
+
export declare function runnerPreflightPermissions(): CredentialPermissionSet;
|
|
127
|
+
export declare function buildPatEnrollmentGuidance(input: {
|
|
128
|
+
repository: CredentialRepositoryIdentity;
|
|
129
|
+
now?: Date;
|
|
130
|
+
}): PatEnrollmentGuidance;
|
|
131
|
+
export declare function buildFineGrainedPatCredentialPolicy(input: {
|
|
132
|
+
repository: CredentialRepositoryIdentity;
|
|
133
|
+
allowedWorkflows: readonly CredentialWorkflowAllowlistEntry[];
|
|
134
|
+
createdAt: Date;
|
|
135
|
+
proof: CredentialPolicyProofMetadata;
|
|
136
|
+
identity?: ActivationIdentity;
|
|
137
|
+
}): CredentialPolicy;
|
|
138
|
+
export declare function buildGitHubAppCredentialPolicy(input: {
|
|
139
|
+
repository: CredentialRepositoryIdentity;
|
|
140
|
+
installation: DiscoveredGitHubAppInstallation;
|
|
141
|
+
allowedWorkflows: readonly CredentialWorkflowAllowlistEntry[];
|
|
142
|
+
createdAt: Date;
|
|
143
|
+
identity?: ActivationIdentity;
|
|
144
|
+
}): CredentialPolicy;
|
|
145
|
+
export declare function appInstallationIssues(installation: DiscoveredGitHubAppInstallation, repository: CredentialRepositoryIdentity): string[];
|
|
146
|
+
export declare function discoverCredentialPlan(input: {
|
|
147
|
+
adapter: GitHubCredentialAdapter;
|
|
148
|
+
repository: CredentialRepositoryIdentity;
|
|
149
|
+
allowedWorkflows: readonly CredentialWorkflowAllowlistEntry[];
|
|
150
|
+
now?: Date;
|
|
151
|
+
}): Promise<CredentialPlan>;
|
|
152
|
+
export declare function enrollFineGrainedPatCredential(input: {
|
|
153
|
+
adapter: GitHubCredentialAdapter;
|
|
154
|
+
prompt: MaskedCredentialPrompt;
|
|
155
|
+
repository: CredentialRepositoryIdentity;
|
|
156
|
+
allowedWorkflows: readonly CredentialWorkflowAllowlistEntry[];
|
|
157
|
+
now?: Date;
|
|
158
|
+
}): Promise<CredentialPolicy>;
|
|
159
|
+
export declare function validateCredentialPolicyUsage(policy: unknown, usage: CredentialPolicyUsage): CredentialPolicyUsageResult;
|
|
160
|
+
export declare function detectCredentialLeaks(inputs: readonly CredentialLeakInput[]): CredentialLeakScanResult;
|
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
import { password } from '@inquirer/prompts';
|
|
2
|
+
import { redactSensitiveText } from '../process-runner.js';
|
|
3
|
+
import { canonicalSha256 } from './canonical-json.js';
|
|
4
|
+
import { currentActivationIdentity } from './graph.js';
|
|
5
|
+
import { credentialPolicySchemaVersion } from './identity.js';
|
|
6
|
+
import { runnerPreflightDisplayNameTemplate, runnerPreflightOrganizationPermissions, runnerPreflightPatLifetimeDays, runnerPreflightRepositoryPermissions, runnerPreflightRotationLeadDays, runnerPreflightSecretName } from './types.js';
|
|
7
|
+
import { validateCredentialPolicy } from './validators.js';
|
|
8
|
+
export const credentialPolicyPathParts = ['governance', 'credentials', 'preflight-policy.json'];
|
|
9
|
+
export class SensitiveCredentialValue {
|
|
10
|
+
#value;
|
|
11
|
+
constructor(value) {
|
|
12
|
+
this.#value = value;
|
|
13
|
+
}
|
|
14
|
+
static fromMaskedInput(value) {
|
|
15
|
+
if (value.length === 0) {
|
|
16
|
+
throw new Error('Credential input cannot be empty.');
|
|
17
|
+
}
|
|
18
|
+
return new SensitiveCredentialValue(value);
|
|
19
|
+
}
|
|
20
|
+
use(consumer) {
|
|
21
|
+
if (this.#value === undefined) {
|
|
22
|
+
throw new Error('Credential value has already been released.');
|
|
23
|
+
}
|
|
24
|
+
return consumer(this.#value);
|
|
25
|
+
}
|
|
26
|
+
release() {
|
|
27
|
+
this.#value = undefined;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export async function inquirerMaskedCredentialPrompt(message) {
|
|
31
|
+
const value = await password({ message, mask: '*' });
|
|
32
|
+
return SensitiveCredentialValue.fromMaskedInput(value);
|
|
33
|
+
}
|
|
34
|
+
export function repositorySecretSetCommand(repository, secretName) {
|
|
35
|
+
return {
|
|
36
|
+
executable: 'gh',
|
|
37
|
+
args: ['secret', 'set', secretName, '--repo', repository.fullName, '--app', 'actions', '--body-file', '-']
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export async function writeRepositorySecretWithGitHubCli(input) {
|
|
41
|
+
const command = repositorySecretSetCommand(input.repository, input.secretName);
|
|
42
|
+
const result = await input.value.use(async (value) => {
|
|
43
|
+
const rawResult = await input.runner.run(command, {
|
|
44
|
+
cwd: input.cwd,
|
|
45
|
+
stdin: value,
|
|
46
|
+
redactValues: [value]
|
|
47
|
+
});
|
|
48
|
+
return {
|
|
49
|
+
...rawResult,
|
|
50
|
+
stdout: redactSensitiveText(rawResult.stdout, [value]),
|
|
51
|
+
stderr: redactSensitiveText(rawResult.stderr, [value]),
|
|
52
|
+
displayCommand: redactSensitiveText(rawResult.displayCommand, [value]),
|
|
53
|
+
...(rawResult.errorMessage
|
|
54
|
+
? { errorMessage: redactSensitiveText(rawResult.errorMessage, [value]) }
|
|
55
|
+
: {})
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
return { command, result };
|
|
59
|
+
}
|
|
60
|
+
function addDays(date, days) {
|
|
61
|
+
return new Date(date.getTime() + days * 24 * 60 * 60 * 1000);
|
|
62
|
+
}
|
|
63
|
+
function canonicalIso(date) {
|
|
64
|
+
return date.toISOString();
|
|
65
|
+
}
|
|
66
|
+
export function canonicalCredentialRepository(input) {
|
|
67
|
+
const owner = input.owner.trim();
|
|
68
|
+
const name = input.name.trim();
|
|
69
|
+
if (!owner || !name || owner.includes('/') || name.includes('/')) {
|
|
70
|
+
throw new Error('Credential repository owner and name must be non-empty path segments.');
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
id: input.id?.trim() || `${owner}/${name}`,
|
|
74
|
+
owner,
|
|
75
|
+
name,
|
|
76
|
+
fullName: `${owner}/${name}`
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
export function repositoryNameFromFullName(fullName) {
|
|
80
|
+
const parts = fullName.trim().split('/');
|
|
81
|
+
const name = parts.at(-1);
|
|
82
|
+
if (!name) {
|
|
83
|
+
throw new Error('Repository full name must include a repository name.');
|
|
84
|
+
}
|
|
85
|
+
return name.toLowerCase();
|
|
86
|
+
}
|
|
87
|
+
export function runnerPreflightDisplayName(repositoryName) {
|
|
88
|
+
return runnerPreflightDisplayNameTemplate.replace('<repo>', repositoryNameFromFullName(repositoryName));
|
|
89
|
+
}
|
|
90
|
+
export function runnerPreflightPermissions() {
|
|
91
|
+
return {
|
|
92
|
+
repository: [...runnerPreflightRepositoryPermissions],
|
|
93
|
+
organization: [...runnerPreflightOrganizationPermissions]
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export function buildPatEnrollmentGuidance(input) {
|
|
97
|
+
const createdAt = input.now ?? new Date();
|
|
98
|
+
const expiresAt = addDays(createdAt, runnerPreflightPatLifetimeDays);
|
|
99
|
+
const rotationDueAt = addDays(expiresAt, -runnerPreflightRotationLeadDays);
|
|
100
|
+
return {
|
|
101
|
+
authKind: 'fine-grained-pat',
|
|
102
|
+
displayNameTemplate: runnerPreflightDisplayNameTemplate,
|
|
103
|
+
displayName: runnerPreflightDisplayName(input.repository.name),
|
|
104
|
+
secretName: runnerPreflightSecretName,
|
|
105
|
+
lifetimeDays: runnerPreflightPatLifetimeDays,
|
|
106
|
+
owner: input.repository.owner,
|
|
107
|
+
repository: input.repository,
|
|
108
|
+
selectedRepositoryOnly: true,
|
|
109
|
+
permissions: runnerPreflightPermissions(),
|
|
110
|
+
writes: [],
|
|
111
|
+
expiresAt: canonicalIso(expiresAt),
|
|
112
|
+
rotationLeadDays: runnerPreflightRotationLeadDays,
|
|
113
|
+
rotationDueAt: canonicalIso(rotationDueAt)
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function digestPayloadFree(value) {
|
|
117
|
+
return canonicalSha256(value);
|
|
118
|
+
}
|
|
119
|
+
function proofMetadata(input) {
|
|
120
|
+
return {
|
|
121
|
+
verifiedAt: input.verifiedAt,
|
|
122
|
+
readbackDigest: input.readbackDigest,
|
|
123
|
+
readbackProvider: input.readbackProvider,
|
|
124
|
+
payloadFree: true
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function normalizeAllowedWorkflows(allowedWorkflows) {
|
|
128
|
+
return allowedWorkflows.map((entry, index) => {
|
|
129
|
+
if (!entry.path || entry.jobs.length === 0) {
|
|
130
|
+
throw new Error(`Allowed credential workflow ${index} must include a path and at least one job.`);
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
path: entry.path,
|
|
134
|
+
jobs: [...entry.jobs]
|
|
135
|
+
};
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
export function buildFineGrainedPatCredentialPolicy(input) {
|
|
139
|
+
const guidance = buildPatEnrollmentGuidance({ repository: input.repository, now: input.createdAt });
|
|
140
|
+
return validateCredentialPolicy({
|
|
141
|
+
schemaVersion: credentialPolicySchemaVersion,
|
|
142
|
+
identity: input.identity ?? currentActivationIdentity,
|
|
143
|
+
repository: input.repository,
|
|
144
|
+
owner: input.repository.owner,
|
|
145
|
+
authKind: 'fine-grained-pat',
|
|
146
|
+
displayNameTemplate: runnerPreflightDisplayNameTemplate,
|
|
147
|
+
displayName: guidance.displayName,
|
|
148
|
+
secretName: runnerPreflightSecretName,
|
|
149
|
+
createdAt: canonicalIso(input.createdAt),
|
|
150
|
+
expiresAt: guidance.expiresAt,
|
|
151
|
+
rotationLeadDays: runnerPreflightRotationLeadDays,
|
|
152
|
+
rotationDueAt: guidance.rotationDueAt,
|
|
153
|
+
permissions: runnerPreflightPermissions(),
|
|
154
|
+
allowedWorkflows: normalizeAllowedWorkflows(input.allowedWorkflows),
|
|
155
|
+
nonForwarding: true,
|
|
156
|
+
status: 'active',
|
|
157
|
+
proof: input.proof,
|
|
158
|
+
app: null,
|
|
159
|
+
pat: {
|
|
160
|
+
lifetimeDays: runnerPreflightPatLifetimeDays,
|
|
161
|
+
selectedRepositoryOnly: true,
|
|
162
|
+
createdBy: 'manual-masked-entry'
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
export function buildGitHubAppCredentialPolicy(input) {
|
|
167
|
+
const app = {
|
|
168
|
+
installationId: input.installation.installationId,
|
|
169
|
+
appSlug: input.installation.appSlug,
|
|
170
|
+
selection: 'selected-repository',
|
|
171
|
+
repositoryFullName: input.repository.fullName,
|
|
172
|
+
permissionsVerifiedAt: input.installation.permissionsVerifiedAt,
|
|
173
|
+
token: {
|
|
174
|
+
strategy: 'installation-token',
|
|
175
|
+
ttlSeconds: input.installation.token.ttlSeconds,
|
|
176
|
+
generatedBy: 'github-app'
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
const readbackDigest = input.installation.readbackDigest ?? digestPayloadFree({
|
|
180
|
+
installationId: app.installationId,
|
|
181
|
+
repository: input.repository.fullName,
|
|
182
|
+
permissions: runnerPreflightPermissions(),
|
|
183
|
+
selectedRepositoryOnly: true
|
|
184
|
+
});
|
|
185
|
+
const expiresAt = addDays(input.createdAt, runnerPreflightPatLifetimeDays);
|
|
186
|
+
const rotationDueAt = addDays(expiresAt, -runnerPreflightRotationLeadDays);
|
|
187
|
+
return validateCredentialPolicy({
|
|
188
|
+
schemaVersion: credentialPolicySchemaVersion,
|
|
189
|
+
identity: input.identity ?? currentActivationIdentity,
|
|
190
|
+
repository: input.repository,
|
|
191
|
+
owner: input.repository.owner,
|
|
192
|
+
authKind: 'github-app',
|
|
193
|
+
displayNameTemplate: runnerPreflightDisplayNameTemplate,
|
|
194
|
+
displayName: runnerPreflightDisplayName(input.repository.name),
|
|
195
|
+
secretName: runnerPreflightSecretName,
|
|
196
|
+
createdAt: canonicalIso(input.createdAt),
|
|
197
|
+
expiresAt: canonicalIso(expiresAt),
|
|
198
|
+
rotationLeadDays: runnerPreflightRotationLeadDays,
|
|
199
|
+
rotationDueAt: canonicalIso(rotationDueAt),
|
|
200
|
+
permissions: runnerPreflightPermissions(),
|
|
201
|
+
allowedWorkflows: normalizeAllowedWorkflows(input.allowedWorkflows),
|
|
202
|
+
nonForwarding: true,
|
|
203
|
+
status: 'active',
|
|
204
|
+
proof: proofMetadata({
|
|
205
|
+
verifiedAt: input.installation.permissionsVerifiedAt,
|
|
206
|
+
readbackDigest,
|
|
207
|
+
readbackProvider: 'github-api'
|
|
208
|
+
}),
|
|
209
|
+
app,
|
|
210
|
+
pat: null
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
function sameRepository(left, right) {
|
|
214
|
+
return left.owner === right.owner &&
|
|
215
|
+
left.name === right.name &&
|
|
216
|
+
left.fullName === right.fullName &&
|
|
217
|
+
left.id === right.id;
|
|
218
|
+
}
|
|
219
|
+
function samePermissionSet(value) {
|
|
220
|
+
return sameStringSet(value.repository, runnerPreflightRepositoryPermissions) &&
|
|
221
|
+
sameStringSet(value.organization, runnerPreflightOrganizationPermissions);
|
|
222
|
+
}
|
|
223
|
+
function sameStringSet(left, right) {
|
|
224
|
+
return left.length === right.length && right.every((entry) => left.includes(entry));
|
|
225
|
+
}
|
|
226
|
+
function writablePermissions(value) {
|
|
227
|
+
return [...value.repository, ...value.organization].filter((entry) => /(^|:)write$/iu.test(entry));
|
|
228
|
+
}
|
|
229
|
+
export function appInstallationIssues(installation, repository) {
|
|
230
|
+
const issues = [];
|
|
231
|
+
if (!installation.approved) {
|
|
232
|
+
issues.push('GitHub App installation is not already approved.');
|
|
233
|
+
}
|
|
234
|
+
if (!installation.verified) {
|
|
235
|
+
issues.push('GitHub App installation readback is not verified.');
|
|
236
|
+
}
|
|
237
|
+
if (installation.selection !== 'selected-repository') {
|
|
238
|
+
issues.push('GitHub App installation is not selected-repository scoped.');
|
|
239
|
+
}
|
|
240
|
+
if (installation.repositories.length !== 1 || !installation.repositories.some((candidate) => sameRepository(candidate, repository))) {
|
|
241
|
+
issues.push('GitHub App selected repository does not exactly match the current repository.');
|
|
242
|
+
}
|
|
243
|
+
if (!samePermissionSet(installation.permissions)) {
|
|
244
|
+
issues.push('GitHub App permissions do not exactly match runner-preflight read requirements.');
|
|
245
|
+
}
|
|
246
|
+
if (writablePermissions(installation.permissions).length > 0) {
|
|
247
|
+
issues.push('GitHub App exposes write permissions.');
|
|
248
|
+
}
|
|
249
|
+
if (!installation.token.canGenerate || installation.token.ttlSeconds <= 0 || installation.token.ttlSeconds > 3600) {
|
|
250
|
+
issues.push('GitHub App cannot generate bounded short-lived installation tokens.');
|
|
251
|
+
}
|
|
252
|
+
return issues;
|
|
253
|
+
}
|
|
254
|
+
export async function discoverCredentialPlan(input) {
|
|
255
|
+
const now = input.now ?? new Date();
|
|
256
|
+
const rejectionReasons = [];
|
|
257
|
+
const installations = await input.adapter.discoverAppInstallations(input.repository);
|
|
258
|
+
for (const installation of installations) {
|
|
259
|
+
const issues = appInstallationIssues(installation, input.repository);
|
|
260
|
+
if (issues.length === 0) {
|
|
261
|
+
return {
|
|
262
|
+
authKind: 'github-app',
|
|
263
|
+
policy: buildGitHubAppCredentialPolicy({
|
|
264
|
+
repository: input.repository,
|
|
265
|
+
installation,
|
|
266
|
+
allowedWorkflows: input.allowedWorkflows,
|
|
267
|
+
createdAt: now
|
|
268
|
+
}),
|
|
269
|
+
app: installation,
|
|
270
|
+
fallbackGuidance: null,
|
|
271
|
+
rejectionReasons
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
rejectionReasons.push(...issues);
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
authKind: 'fine-grained-pat',
|
|
278
|
+
policy: null,
|
|
279
|
+
app: null,
|
|
280
|
+
fallbackGuidance: buildPatEnrollmentGuidance({ repository: input.repository, now }),
|
|
281
|
+
rejectionReasons
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
export async function enrollFineGrainedPatCredential(input) {
|
|
285
|
+
if (!input.adapter.setRepositorySecret) {
|
|
286
|
+
throw new Error('Repository-secret adapter does not support in-memory secret writes.');
|
|
287
|
+
}
|
|
288
|
+
const createdAt = input.now ?? new Date();
|
|
289
|
+
const credential = await input.prompt('Paste the fine-grained PAT. Input is masked and is not logged.');
|
|
290
|
+
try {
|
|
291
|
+
const readback = await input.adapter.setRepositorySecret({
|
|
292
|
+
repository: input.repository,
|
|
293
|
+
secretName: runnerPreflightSecretName,
|
|
294
|
+
value: credential
|
|
295
|
+
});
|
|
296
|
+
if (!sameRepository(readback.repository, input.repository)) {
|
|
297
|
+
throw new Error('Repository secret readback repository does not match the credential policy repository.');
|
|
298
|
+
}
|
|
299
|
+
if (readback.secretName !== runnerPreflightSecretName) {
|
|
300
|
+
throw new Error('Repository secret readback secret name does not match the fixed credential policy secret.');
|
|
301
|
+
}
|
|
302
|
+
return buildFineGrainedPatCredentialPolicy({
|
|
303
|
+
repository: input.repository,
|
|
304
|
+
allowedWorkflows: input.allowedWorkflows,
|
|
305
|
+
createdAt,
|
|
306
|
+
proof: proofMetadata({
|
|
307
|
+
verifiedAt: readback.updatedAt,
|
|
308
|
+
readbackDigest: readback.readbackDigest,
|
|
309
|
+
readbackProvider: 'github-api'
|
|
310
|
+
})
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
finally {
|
|
314
|
+
credential.release();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
export function validateCredentialPolicyUsage(policy, usage) {
|
|
318
|
+
const validated = validateCredentialPolicy(policy);
|
|
319
|
+
const issues = [];
|
|
320
|
+
if (validated.status === 'compromised') {
|
|
321
|
+
issues.push('Credential policy is compromised and must be revoked and rotated before use.');
|
|
322
|
+
}
|
|
323
|
+
if (validated.status === 'expired') {
|
|
324
|
+
issues.push('Credential policy is already expired.');
|
|
325
|
+
}
|
|
326
|
+
if (validated.status === 'expiring') {
|
|
327
|
+
issues.push('Credential policy is inside its rotation window.');
|
|
328
|
+
}
|
|
329
|
+
if (!sameRepository(validated.repository, usage.repository)) {
|
|
330
|
+
issues.push('Credential policy repository does not match the requested repository.');
|
|
331
|
+
}
|
|
332
|
+
if (!samePermissionSet(validated.permissions) || !samePermissionSet(usage.permissions)) {
|
|
333
|
+
issues.push('Credential permissions must exactly match metadata read, hosted-runners read, and network-configurations read.');
|
|
334
|
+
}
|
|
335
|
+
const writable = [...writablePermissions(validated.permissions), ...writablePermissions(usage.permissions)];
|
|
336
|
+
if (writable.length > 0) {
|
|
337
|
+
issues.push(`Credential permissions must not include writes: ${writable.join(', ')}.`);
|
|
338
|
+
}
|
|
339
|
+
if (usage.forwardsCredential || validated.nonForwarding !== true) {
|
|
340
|
+
issues.push('Credential forwarding is not allowed.');
|
|
341
|
+
}
|
|
342
|
+
for (const reference of usage.references) {
|
|
343
|
+
const allowed = validated.allowedWorkflows.find((entry) => entry.path === reference.workflowPath);
|
|
344
|
+
if (!allowed || !allowed.jobs.includes(reference.job)) {
|
|
345
|
+
issues.push(`Credential use by ${reference.workflowPath}#${reference.job} is outside the exact workflow/job allowlist.`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const now = usage.now ?? new Date();
|
|
349
|
+
if (Date.parse(validated.expiresAt) <= now.getTime()) {
|
|
350
|
+
issues.push('Credential policy is expired.');
|
|
351
|
+
}
|
|
352
|
+
if (Date.parse(validated.rotationDueAt) <= now.getTime()) {
|
|
353
|
+
issues.push('Credential policy is inside its rotation lead window.');
|
|
354
|
+
}
|
|
355
|
+
if (usage.verifiedReadbackDigest !== validated.proof.readbackDigest) {
|
|
356
|
+
issues.push('Credential policy lacks matching verified payload-free readback.');
|
|
357
|
+
}
|
|
358
|
+
if (validated.authKind === 'github-app') {
|
|
359
|
+
if (!validated.app ||
|
|
360
|
+
validated.pat !== null ||
|
|
361
|
+
validated.app.selection !== 'selected-repository' ||
|
|
362
|
+
validated.app.repositoryFullName !== validated.repository.fullName ||
|
|
363
|
+
validated.app.token.strategy !== 'installation-token' ||
|
|
364
|
+
validated.app.token.ttlSeconds <= 0 ||
|
|
365
|
+
validated.app.token.ttlSeconds > 3600) {
|
|
366
|
+
issues.push('GitHub App credential policy is not a supported selected-repository installation token configuration.');
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
else if (!validated.pat || validated.app !== null) {
|
|
370
|
+
issues.push('Fine-grained PAT credential policy has inconsistent auth metadata.');
|
|
371
|
+
}
|
|
372
|
+
return {
|
|
373
|
+
ready: issues.length === 0,
|
|
374
|
+
status: issues.length === 0 ? validated.status : 'not-ready',
|
|
375
|
+
issues
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
const credentialLeakPatterns = [
|
|
379
|
+
{ name: 'classic-github-token', pattern: /\bgh[oprsu]_[A-Za-z0-9_]{20,}\b/u },
|
|
380
|
+
{ name: 'fine-grained-github-pat', pattern: /\bgithub_pat_[A-Za-z0-9_]{20,}\b/u },
|
|
381
|
+
{ name: 'slack-webhook', pattern: /https:\/\/hooks\.slack\.com\/services\/[A-Za-z0-9/]+/u },
|
|
382
|
+
{ name: 'azure-account-key', pattern: /\bAccountKey=[^;\s]+/iu },
|
|
383
|
+
{ name: 'private-key', pattern: /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/u }
|
|
384
|
+
];
|
|
385
|
+
export function detectCredentialLeaks(inputs) {
|
|
386
|
+
const leaks = inputs.flatMap((input) => credentialLeakPatterns
|
|
387
|
+
.filter((entry) => entry.pattern.test(input.text))
|
|
388
|
+
.map((entry) => ({ source: input.source, label: input.label, pattern: entry.name })));
|
|
389
|
+
return {
|
|
390
|
+
status: leaks.length > 0 ? 'compromised' : 'clear',
|
|
391
|
+
leaks,
|
|
392
|
+
guidance: leaks.length === 0
|
|
393
|
+
? []
|
|
394
|
+
: [
|
|
395
|
+
'Treat the credential as compromised.',
|
|
396
|
+
'Revoke the exposed credential in GitHub or its issuing system.',
|
|
397
|
+
'Create a fresh deterministic replacement and rotate the repository secret after verified readback.',
|
|
398
|
+
'Liftoff did not attempt automatic revocation.'
|
|
399
|
+
],
|
|
400
|
+
unauthorizedRevocationAttempted: false
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/governance-activation/credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { LiftoffManifest } from '../types.js';
|
|
2
|
+
export interface GovernanceDoctorCheck {
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
severity: 'ok' | 'warn' | 'fail' | 'skipped';
|
|
6
|
+
state: string;
|
|
7
|
+
detail: string;
|
|
8
|
+
remedy?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function governanceDoctorChecks(projectRoot: string, manifest: LiftoffManifest, now?: Date): Promise<GovernanceDoctorCheck[]>;
|