Skip to content
Draft
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
23 changes: 15 additions & 8 deletions build-tools/cncluster
Original file line number Diff line number Diff line change
Expand Up @@ -989,16 +989,23 @@ subcommand_whitelist[cluster_enable_workload_identity]='Enable workload identity
function subcmd_cluster_enable_workload_identity() {
if gcloud container clusters describe "${GCP_CLUSTER_NAME}" --format="value(workloadIdentityConfig)" | grep -q "workloadPool"; then
_info "Workload identity is already enabled for the cluster."
return
else
_info "Enabling workload identity for the cluster."
gcloud container clusters update "${GCP_CLUSTER_NAME}" --workload-pool="${CLOUDSDK_CORE_PROJECT}.svc.id.goog"
fi

_info "Enabling workload identity for the cluster."
gcloud container clusters update "${GCP_CLUSTER_NAME}" --workload-pool="${CLOUDSDK_CORE_PROJECT}.svc.id.goog"

_info "Enabling GKE metadata on the cn-apps node pool."
gcloud container node-pools update cn-apps-pool \
--cluster "cn-${GCP_CLUSTER_BASENAME}net" \
--workload-metadata=GKE_METADATA
local pool current_mode
for pool in cn-apps-pool cn-apps-node-pool-hd cn-infra-node-pool gke-node-pool; do
if gcloud container node-pools describe "${pool}" --cluster "${GCP_CLUSTER_NAME}" --format="value(name)" &>/dev/null; then
current_mode=$(gcloud container node-pools describe "${pool}" --cluster "${GCP_CLUSTER_NAME}" --format="value(config.workloadMetadataConfig.mode)" 2>/dev/null || true)
if [[ "${current_mode}" == "GKE_METADATA" ]]; then
_info "Workload metadata already GKE_METADATA for ${pool}."
else
_info "Enabling GKE metadata on node pool ${pool}."
gcloud container node-pools update "${pool}" --cluster "${GCP_CLUSTER_NAME}" --workload-metadata=GKE_METADATA
fi
fi
done
}

subcommand_whitelist[cluster_enable_http_load_balancing]='Enable http load balancing for the cluster.'
Expand Down
1 change: 1 addition & 0 deletions cluster/deployment/scratchneta/config.resolved.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ cluster:
minNodes: 1
nodeType: 'n4d-standard-8'
infra:
certManagerUseWorkloadIdentity: true
gkeGateway:
proxyForIstioHttp: false
istio:
Expand Down
6 changes: 5 additions & 1 deletion cluster/deployment/scratchneta/config.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
!include($SPLICE_ROOT/cluster/configs/shared/scratchnet.yaml) {}
!include($SPLICE_ROOT/cluster/configs/shared/scratchnet.yaml) {
infra: {
certManagerUseWorkloadIdentity: true
}
}
3 changes: 3 additions & 0 deletions cluster/pulumi/infra/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const InfraConfigSchema = z.object({
})
.optional(),
enableGCReaperJob: z.boolean().default(false),
certManagerUseWorkloadIdentity: z.boolean().optional(),
gkeGateway: z.object({
proxyForIstioHttp: z.boolean(),
}),
Expand Down Expand Up @@ -73,6 +74,8 @@ export type Config = z.infer<typeof InfraConfigSchema>;
// @ts-ignore
const fullConfig = InfraConfigSchema.parse(clusterYamlConfig);
export const enableGCReaperJob = fullConfig.infra.enableGCReaperJob;
export const certManagerUseWorkloadIdentity =
fullConfig.infra.certManagerUseWorkloadIdentity ?? false;
console.error(
`Loaded infra config: ${util.inspect(fullConfig, {
depth: null,
Expand Down
94 changes: 63 additions & 31 deletions cluster/pulumi/infra/src/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ import {
import { infraAffinityAndTolerations } from '@canton-network/splice-pulumi-common';
import { svConfigsBasic } from '@canton-network/splice-pulumi-common-sv/src/svConfigsBasic';

import { gcpDnsProject } from './config';
import { certManagerUseWorkloadIdentity, gcpDnsProject } from './config';

const useCertManagerWorkloadIdentity = certManagerUseWorkloadIdentity;
const dns01SaIamAccount = useCertManagerWorkloadIdentity
? config.requireEnv('DNS01_SA_IAM_ACCOUNT')
: config.optionalEnv('DNS01_SA_IAM_ACCOUNT') || '';

function ipAddress(addressName: string): gcp.compute.Address {
return new gcp.compute.Address(addressName, {
Expand Down Expand Up @@ -78,6 +83,20 @@ function certManager(certManagerNamespaceName: string): certmanager.CertManager
},
});

const workloadIdentityArgs: Partial<certmanager.CertManagerArgs> = useCertManagerWorkloadIdentity
? {
extraArgs: [
'--issuer-ambient-credentials=true',
'--cluster-issuer-ambient-credentials=true',
],
serviceAccount: {
annotations: {
'iam.gke.io/gcp-service-account': dns01SaIamAccount,
},
},
}
: {};

return new certmanager.CertManager('cert-manager', {
installCRDs: true,
helmOptions: {
Expand All @@ -94,6 +113,7 @@ function certManager(certManagerNamespaceName: string): certmanager.CertManager
startupapicheck: {
...infraAffinityAndTolerations,
},
...workloadIdentityArgs,
});
}

Expand Down Expand Up @@ -140,13 +160,17 @@ function clusterCertificate(
solvers: [
{
dns01: {
cloudDNS: {
project: 'da-gcp-canton-domain',
serviceAccountSecretRef: {
key: 'key.json',
name: 'clouddns-dns01-solver-svc-acct',
},
},
cloudDNS: useCertManagerWorkloadIdentity
? {
project: 'da-gcp-canton-domain',
}
: {
project: 'da-gcp-canton-domain',
serviceAccountSecretRef: {
key: 'key.json',
name: 'clouddns-dns01-solver-svc-acct',
},
},
},
},
],
Expand All @@ -158,30 +182,38 @@ function clusterCertificate(
}
);

const gcpSecretName = config.requireEnv('DNS01_SA_KEY_SECRET');

gcp.secretmanager.SecretVersion.get(
'dns01-sa-key-secret',
`projects/${GCP_PROJECT}/secrets/${gcpSecretName}/versions/latest`
).secretData.apply(dns01SaKeySecret => {
new k8s.core.v1.Secret(
'clouddns-dns01-solver-svc-acct',
{
metadata: {
name: 'clouddns-dns01-solver-svc-acct',
namespace: ns.metadata.name,
},
type: 'Opaque',
data: {
// TODO(#973): Handle this correctly in dump-config. Currently it gets here with an undefined value.
'key.json': btoa(dns01SaKeySecret || 'dns-secret'),
if (useCertManagerWorkloadIdentity) {
new gcp.serviceaccount.IAMMember('dns01-solver-workload-identity-user', {
serviceAccountId: `projects/${gcpDnsProject}/serviceAccounts/${dns01SaIamAccount}`,
role: 'roles/iam.workloadIdentityUser',
member: pulumi.interpolate`serviceAccount:${GCP_PROJECT}.svc.id.goog[cert-manager/cert-manager]`,
});
} else {
const gcpSecretName = config.requireEnv('DNS01_SA_KEY_SECRET');

gcp.secretmanager.SecretVersion.get(
'dns01-sa-key-secret',
`projects/${GCP_PROJECT}/secrets/${gcpSecretName}/versions/latest`
).secretData.apply(dns01SaKeySecret => {
new k8s.core.v1.Secret(
'clouddns-dns01-solver-svc-acct',
{
metadata: {
name: 'clouddns-dns01-solver-svc-acct',
namespace: ns.metadata.name,
},
type: 'Opaque',
data: {
// TODO(#973): Handle this correctly in dump-config. Currently it gets here with an undefined value.
'key.json': btoa(dns01SaKeySecret || 'dns-secret'),
},
},
},
{
dependsOn: ns,
}
);
});
{
dependsOn: ns,
}
);
});
}

const certDnsNames = dnsNames
.map(dnsName =>
Expand Down
Loading