Skip to content

Instantly share code, notes, and snippets.

@rezamt
Last active September 2, 2025 04:19
Show Gist options
  • Save rezamt/c8c5652722a4655c40d0a7707eb73e49 to your computer and use it in GitHub Desktop.
Save rezamt/c8c5652722a4655c40d0a7707eb73e49 to your computer and use it in GitHub Desktop.
Corssplane Upbound
# Check ./provider-in-cluster.yaml to see how to grant permissions to the Provider
apiVersion: kubernetes.crossplane.io/v1alpha1
kind: ProviderConfig
metadata:
name: up-provider-kubernetes-config
spec:
credentials:
source: InjectedIdentity
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: up-provider-kubernetes
spec:
package: xpkg.upbound.io/upbound/provider-kubernetes:v0.18.1
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xclientcertificates.compositions.azuread.inuit.io
spec:
group: compositions.azuread.inuit.io
names:
categories:
- crossplane
- managed
- azuread
kind: xClientCertificates
listKind: xClientCertificatesList
plural: xclientcertificates
singular: xclientcertificate
claimNames:
kind: ClientCertificate # Changed to singular to match your desired claim
plural: clientcertificates
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
properties:
apiVersion:
type: string
kind:
type: string
metadata:
type: object
spec:
properties:
encoding:
type: string # pem, base64, hex
default: pem
# Specifies the encoding used for the supplied certificate data. Must be one of pem, base64 or hex. Defaults to pem. Specifies the encoding used for the supplied certificate data
endDate:
type: string # 2018-01-01T01:02:03Z | RFC3339
# The end date until which the certificate is valid, formatted as an RFC3339 date string (e.g. 2018-01-01T01:02:03Z). If omitted, the API will decide a suitable expiry date, which is typically around 2 years from the start date. Changing this field forces a new resource to be created. The end date until which the certificate is valid, formatted as an RFC3339 date string (e.g. 2018-01-01T01:02:03Z). If omitted, the API will decide a suitable expiry date, which is typically around 2 years from the start date
endDateRelative:
type: string # 240h (10 days) or 2400h30m
# A relative duration for which the certificate is valid until, for example 240h (10 days) or 2400h30m. Changing this field forces a new resource to be created. A relative duration for which the certificate is valid until, for example 240h (10 days) or 2400h30m
startDate:
type: string # 2018-01-01T01:02:03Z | RFC3339
# The start date from which the certificate is valid, formatted as an RFC3339 date string (e.g. 2018-01-01T01:02:03Z). If this isn't specified, the value is determined by Azure Active Directory and is usually the start date of the certificate for asymmetric keys, or the current timestamp for symmetric keys. Changing this field forces a new resource to be created. The start date from which the certificate is valid, formatted as an RFC3339 date string (e.g. 2018-01-01T01:02:03Z). If this isn't specified, the current date and time are use
type:
type: string # AsymmetricX509Cert or Symmetric
# The type of key/certificate. Must be one of AsymmetricX509Cert or Symmetric. Changing this fields forces a new resource to be created. The type of key/certificate
cert:
type: string
# a certificate (public key) with one of the following file types: .cer, .pem, .crt
required:
- type
- cert
type: object
required:
- spec
type: object
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xfederatedidentities.compositions.azuread.inuit.io
spec:
group: compositions.azuread.inuit.io
names:
categories:
- crossplane
- managed
- azuread
kind: xFederatedIdentities
listKind: xFederatedIdentitiesList
plural: xfederatedidentities
singular: xfederatedidentity
claimNames:
kind: FederatedIdentity # Changed to singular to match your desired claim
plural: federatedidentities
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
properties:
apiVersion:
type: string
kind:
type: string
metadata:
type: object
spec:
properties:
audiences:
items:
type: string
type: array
description:
type: string
displayName:
type: string
issuer:
type: string
subject:
type: string
required:
- audiences
- displayName
- issuer
- subject
type: object
required:
- spec
type: object
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: xclientcertificates.compositions.azuread.inuit.io-v1alpha1
spec:
compositeTypeRef:
apiVersion: compositions.azuread.inuit.io/v1alpha1
kind: xClientCertificates
patchSets:
resources:
- name: certificate-secret
base:
apiVersion: kubernetes.crossplane.io/v1alpha2
kind: Object
metadata:
spec:
forProvider:
manifest:
apiVersion: v1
kind: Secret
metadata:
name: helloupbound-secert
namespace: crossplane-system # is mandatory
type: Opaque
stringData: {} # Remove the empty "value: ''" from here
providerConfigRef: # is mandatory but check again
name: up-provider-kubernetes-config
patches:
- type: FromCompositeFieldPath
fromFieldPath: metadata.name
toFieldPath: metadata.name
transforms:
- type: string
string:
fmt: "%s-secret"
- type: FromCompositeFieldPath
fromFieldPath: metadata.name
toFieldPath: spec.forProvider.manifest.metadata.name
transforms:
- type: string
string:
fmt: "%s-secret"
- type: FromCompositeFieldPath
fromFieldPath: spec.cert
toFieldPath: spec.forProvider.manifest.stringData.value
policy:
fromFieldPath: Required
- name: certificate
base:
apiVersion: applications.azuread.upbound.io/v1beta1
kind: Certificate
metadata:
annotations:
meta.upbound.io/example-id: applications/v1beta1/application
labels:
testing.upbound.io/example-name: example
spec:
forProvider:
applicationObjectIdSelector:
matchLabels:
testing.upbound.io/example-name: example
# type: AsymmetricX509Cert
valueSecretRef:
key: value
name: helloupbound-secert
namespace: crossplane-system
patches:
# Patch the certificate resource name
- type: FromCompositeFieldPath
fromFieldPath: metadata.name
toFieldPath: metadata.name
transforms:
- type: string
string:
fmt: "%s-cert"
# Patch the secret name reference to match the generated secret name
- type: FromCompositeFieldPath
fromFieldPath: metadata.name
toFieldPath: spec.forProvider.valueSecretRef.name
transforms:
- type: string
string:
fmt: "%s-secret"
- type: FromCompositeFieldPath
fromFieldPath: spec.type
toFieldPath: spec.forProvider.type
policy:
fromFieldPath: Required
- type: FromCompositeFieldPath
fromFieldPath: spec.encoding
toFieldPath: spec.forProvider.encoding
policy:
fromFieldPath: Optional
- type: FromCompositeFieldPath
fromFieldPath: spec.startDate
toFieldPath: spec.forProvider.startDate
policy:
fromFieldPath: Optional
- type: FromCompositeFieldPath
fromFieldPath: spec.endDate
toFieldPath: spec.forProvider.endDate
policy:
fromFieldPath: Optional
- type: FromCompositeFieldPath
fromFieldPath: spec.endDateRelative
toFieldPath: spec.forProvider.endDateRelative
policy:
fromFieldPath: Optional
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: xfederatedidentities.compositions.azuread.inuit.io-v1alpha1
spec:
compositeTypeRef:
apiVersion: compositions.azuread.inuit.io/v1alpha1
kind: xFederatedIdentities
patchSets:
resources:
- name: federated-identity
base:
apiVersion: applications.azuread.upbound.io/v1beta1
kind: FederatedIdentityCredential
metadata:
annotations:
meta.upbound.io/example-id: applications/v1beta1/application
labels:
testing.upbound.io/example-name: example
spec:
forProvider:
applicationObjectIdSelector:
matchLabels:
testing.upbound.io/example-name: example
patches:
- type: CombineFromComposite
combine:
variables:
- fromFieldPath: metadata.name
strategy: string
string:
fmt: "%s-federated-identity"
toFieldPath: metadata.name
- type: FromCompositeFieldPath
fromFieldPath: spec.audiences
toFieldPath: spec.forProvider.audiences
policy:
fromFieldPath: Required
- type: FromCompositeFieldPath
fromFieldPath: spec.description
toFieldPath: spec.forProvider.description
policy:
fromFieldPath: Optional # Made optional since it's not in required fields
- type: FromCompositeFieldPath
fromFieldPath: spec.displayName
toFieldPath: spec.forProvider.displayName
policy:
fromFieldPath: Required
- type: FromCompositeFieldPath
fromFieldPath: spec.issuer
toFieldPath: spec.forProvider.issuer
policy:
fromFieldPath: Required
- type: FromCompositeFieldPath
fromFieldPath: spec.subject
toFieldPath: spec.forProvider.subject
policy:
fromFieldPath: Required
cat > cert.pem << 'EOF'
-----BEGIN CERTIFICATE-----
MIIDrTCCApWgAwIBAgIUamFCIm30UdV5nV8cbI6GFYpVX4swDQYJKoZIhvcNAQEL
BQAwZjELMAkGA1UEBhMCQVUxDDAKBgNVBAgMA1ZJQzESMBAGA1UEBwwJTWVsYm91
cm5lMQ0wCwYDVQQKDAREZW1vMQswCQYDVQQLDAJJVDEZMBcGA1UEAwwQZGVtby5l
eGFtcGxlLmNvbTAeFw0yNTA4MjYwOTA1MjhaFw0yNjA4MjYwOTA1MjhaMGYxCzAJ
BgNVBAYTAkFVMQwwCgYDVQQIDANWSUMxEjAQBgNVBAcMCU1lbGJvdXJuZTENMAsG
A1UECgwERGVtbzELMAkGA1UECwwCSVQxGTAXBgNVBAMMEGRlbW8uZXhhbXBsZS5j
b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrBZ5/h+Z3S0rOKu3e
QeYJ3PBUemolKlnGjGJzhUPJ9tDOYznyrqLF69QTYghFZO0T3PpSxzjgpvAf9mw8
TymRUujyHd+H3PgIJYISzia6eJAFD5lJZATNGPoIU/31iT/6wt42L3tXM8NvRsR7
9gssxydkABbgsX+Aipo1ooJF10G+E1d4SAQ0TtXZFmDwA0qpwbLwc5JYiMPcUnyG
zTbtGII66ECE/ZiE47kFt6tzjwsOzSlKXd7NV+C4a7P6F9EVmTxD+SBM9WCC0wWj
lfXyZKur32JqvrlLJkXBiXuuaqhxWjTkDy2OALQjj1Gir/yKWxiQiRiYlTa9I+kZ
OCrpAgMBAAGjUzBRMB0GA1UdDgQWBBQZiliWDrRDgX6mJAqMbV2Ml6/BfTAfBgNV
HSMEGDAWgBQZiliWDrRDgX6mJAqMbV2Ml6/BfTAPBgNVHRMBAf8EBTADAQH/MA0G
CSqGSIb3DQEBCwUAA4IBAQBZTDjcqSBUzn0GL06NEAuj1h0fUaQqsqRChZ8vmnmO
NuBNNLz7SK0++nEWj65Yc+oyu+5c8bkXoRYmhxaWFmwELFM29ms7Yl9hr35IEINc
UaU5diQbjHWPgcNIzFM+PQEkw/ZJo9RnhaG42oqiUDEGK4fOPYsTOFM0GbI/syA1
jNfZNnX85wRfRySXy7tyYc7TyDINkW8xpKy/VRq3+asMM06jF6kK2Ai+Xn+n9Qth
qi9iXEl3rvcysO7Uh8JnhnsGWWIt6XI3CiwLx65dXtIUi/UvBcgA5N4weNZViVSL
ncBeaumJUMhcuDmpdKS9/bN75hFR4KuHzSk41t+my8UN
-----END CERTIFICATE-----
EOF

openssl x509 -in cert.pem -noout -startdate -enddate | while read line; do
  if [[ $line == notBefore* ]]; then
    datestr=$(echo $line | sed 's/notBefore=//')
    echo "startDate: \"$(date -u -jf "%b %d %H:%M:%S %Y %Z" "$datestr" "+%Y-%m-%dT%H:%M:%SZ")\""
  elif [[ $line == notAfter* ]]; then
    datestr=$(echo $line | sed 's/notAfter=//')
    echo "endDate: \"$(date -u -jf "%b %d %H:%M:%S %Y %Z" "$datestr" "+%Y-%m-%dT%H:%M:%SZ")\""
  fi
done

# Result should be
# startDate: "2025-08-26T09:05:28Z"
# endDate: "2026-08-26T09:05:28Z"

Configuring Kubernetes Provider


kubectl apply -f 00_crossplane-provider-kubernetes.yaml

# Need a Service Account
# For in cluster changes 
SA=$(kubectl -n crossplane-system get sa -o name | grep up-provider-kubernetes | sed -e 's|serviceaccount\/|crossplane-system:|g')
kubectl delete clusterrolebinding provider-kubernetes-admin-binding # if exist
kubectl create clusterrolebinding provider-kubernetes-admin-binding --clusterrole cluster-admin --serviceaccount="${SA}"

# then apply the configuration
kubectl apply -f 00_crossplane-provider-config-kubernetes.yaml
---
apiVersion: compositions.azuread.inuit.io/v1alpha1
kind: OauthApplication
metadata:
name: helloupbound
spec:
applicationName: Hello Upbound
enabled: true
---
apiVersion: compositions.azuread.inuit.io/v1alpha1
kind: ClientCertificate
metadata:
name: helloupbound-certificate01
namespace: default
spec:
type: "AsymmetricX509Cert"
encoding: "pem"
startDate: "2025-08-26T09:05:28Z" # Optional - Extracted from certificate
endDate: "2026-08-26T09:05:28Z" # Optional - Extracted from certificate
# endDateRelative: "8712h" # 1 year validity
cert: |-
-----BEGIN CERTIFICATE-----
MIIDrTCCApWgAwIBAgIUamFCIm30UdV5nV8cbI6GFYpVX4swDQYJKoZIhvcNAQEL
BQAwZjELMAkGA1UEBhMCQVUxDDAKBgNVBAgMA1ZJQzESMBAGA1UEBwwJTWVsYm91
cm5lMQ0wCwYDVQQKDAREZW1vMQswCQYDVQQLDAJJVDEZMBcGA1UEAwwQZGVtby5l
eGFtcGxlLmNvbTAeFw0yNTA4MjYwOTA1MjhaFw0yNjA4MjYwOTA1MjhaMGYxCzAJ
BgNVBAYTAkFVMQwwCgYDVQQIDANWSUMxEjAQBgNVBAcMCU1lbGJvdXJuZTENMAsG
A1UECgwERGVtbzELMAkGA1UECwwCSVQxGTAXBgNVBAMMEGRlbW8uZXhhbXBsZS5j
b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrBZ5/h+Z3S0rOKu3e
QeYJ3PBUemolKlnGjGJzhUPJ9tDOYznyrqLF69QTYghFZO0T3PpSxzjgpvAf9mw8
TymRUujyHd+H3PgIJYISzia6eJAFD5lJZATNGPoIU/31iT/6wt42L3tXM8NvRsR7
9gssxydkABbgsX+Aipo1ooJF10G+E1d4SAQ0TtXZFmDwA0qpwbLwc5JYiMPcUnyG
zTbtGII66ECE/ZiE47kFt6tzjwsOzSlKXd7NV+C4a7P6F9EVmTxD+SBM9WCC0wWj
lfXyZKur32JqvrlLJkXBiXuuaqhxWjTkDy2OALQjj1Gir/yKWxiQiRiYlTa9I+kZ
OCrpAgMBAAGjUzBRMB0GA1UdDgQWBBQZiliWDrRDgX6mJAqMbV2Ml6/BfTAfBgNV
HSMEGDAWgBQZiliWDrRDgX6mJAqMbV2Ml6/BfTAPBgNVHRMBAf8EBTADAQH/MA0G
CSqGSIb3DQEBCwUAA4IBAQBZTDjcqSBUzn0GL06NEAuj1h0fUaQqsqRChZ8vmnmO
NuBNNLz7SK0++nEWj65Yc+oyu+5c8bkXoRYmhxaWFmwELFM29ms7Yl9hr35IEINc
UaU5diQbjHWPgcNIzFM+PQEkw/ZJo9RnhaG42oqiUDEGK4fOPYsTOFM0GbI/syA1
jNfZNnX85wRfRySXy7tyYc7TyDINkW8xpKy/VRq3+asMM06jF6kK2Ai+Xn+n9Qth
qi9iXEl3rvcysO7Uh8JnhnsGWWIt6XI3CiwLx65dXtIUi/UvBcgA5N4weNZViVSL
ncBeaumJUMhcuDmpdKS9/bN75hFR4KuHzSk41t+my8UN
-----END CERTIFICATE-----
---
apiVersion: compositions.azuread.inuit.io/v1alpha1
kind: ClientCertificate
metadata:
name: helloupbound-certificate02
namespace: default
spec:
type: "AsymmetricX509Cert"
encoding: "pem"
startDate: "2025-08-26T09:05:28Z" # Optional - Extracted from certificate
endDate: "2026-08-26T09:05:28Z" # Optional - Extracted from certificate
# endDateRelative: "8712h" # Optional - 1 year validity
cert: |-
-----BEGIN CERTIFICATE-----
MIIDrTCCApWgAwIBAgIUamFCIm30UdV5nV8cbI6GFYpVX4swDQYJKoZIhvcNAQEL
BQAwZjELMAkGA1UEBhMCQVUxDDAKBgNVBAgMA1ZJQzESMBAGA1UEBwwJTWVsYm91
cm5lMQ0wCwYDVQQKDAREZW1vMQswCQYDVQQLDAJJVDEZMBcGA1UEAwwQZGVtby5l
eGFtcGxlLmNvbTAeFw0yNTA4MjYwOTA1MjhaFw0yNjA4MjYwOTA1MjhaMGYxCzAJ
BgNVBAYTAkFVMQwwCgYDVQQIDANWSUMxEjAQBgNVBAcMCU1lbGJvdXJuZTENMAsG
A1UECgwERGVtbzELMAkGA1UECwwCSVQxGTAXBgNVBAMMEGRlbW8uZXhhbXBsZS5j
b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrBZ5/h+Z3S0rOKu3e
QeYJ3PBUemolKlnGjGJzhUPJ9tDOYznyrqLF69QTYghFZO0T3PpSxzjgpvAf9mw8
TymRUujyHd+H3PgIJYISzia6eJAFD5lJZATNGPoIU/31iT/6wt42L3tXM8NvRsR7
9gssxydkABbgsX+Aipo1ooJF10G+E1d4SAQ0TtXZFmDwA0qpwbLwc5JYiMPcUnyG
zTbtGII66ECE/ZiE47kFt6tzjwsOzSlKXd7NV+C4a7P6F9EVmTxD+SBM9WCC0wWj
lfXyZKur32JqvrlLJkXBiXuuaqhxWjTkDy2OALQjj1Gir/yKWxiQiRiYlTa9I+kZ
OCrpAgMBAAGjUzBRMB0GA1UdDgQWBBQZiliWDrRDgX6mJAqMbV2Ml6/BfTAfBgNV
HSMEGDAWgBQZiliWDrRDgX6mJAqMbV2Ml6/BfTAPBgNVHRMBAf8EBTADAQH/MA0G
CSqGSIb3DQEBCwUAA4IBAQBZTDjcqSBUzn0GL06NEAuj1h0fUaQqsqRChZ8vmnmO
NuBNNLz7SK0++nEWj65Yc+oyu+5c8bkXoRYmhxaWFmwELFM29ms7Yl9hr35IEINc
UaU5diQbjHWPgcNIzFM+PQEkw/ZJo9RnhaG42oqiUDEGK4fOPYsTOFM0GbI/syA1
jNfZNnX85wRfRySXy7tyYc7TyDINkW8xpKy/VRq3+asMM06jF6kK2Ai+Xn+n9Qth
qi9iXEl3rvcysO7Uh8JnhnsGWWIt6XI3CiwLx65dXtIUi/UvBcgA5N4weNZViVSL
ncBeaumJUMhcuDmpdKS9/bN75hFR4KuHzSk41t+my8UN
-----END CERTIFICATE-----
---
apiVersion: compositions.azuread.inuit.io/v1alpha1
kind: FederatedIdentity
metadata:
name: helloupbound
spec:
audiences:
- api://AzureADTokenExchange
description: Deployments for my-repo
displayName: my-git-repo-deploy
issuer: https://token.actions.githubusercontent.com
subject: repo:my-organization/my-repo:environment:prod
---
apiVersion: compositions.azuread.inuit.io/v1alpha1
kind: FederatedIdentity
metadata:
name: spiffe-workload-credential
spec:
audiences:
- api://AzureADTokenExchange
description: Federated credential for SPIFFE workload identity
displayName: spiffe-workload-credential
issuer: https://spire-server.example.com
subject: spiffe://example.com/workload/my-service
---
apiVersion: compositions.azuread.inuit.io/v1alpha1
kind: FederatedIdentity
metadata:
name: terraform-cloud-credential
spec:
audiences:
- api://AzureADTokenExchange
description: Federated credential for Terraform Cloud runs
displayName: terraform-cloud-credential
issuer: https://app.terraform.io
subject: "organization:{org-name}:project:{project-name}:workspace:{workspace-name}:run_phase:plan"
---
apiVersion: compositions.azuread.inuit.io/v1alpha1
kind: FederatedIdentity
metadata:
name: custom-oidc-provider
spec:
audiences:
- api://AzureADTokenExchange
description: "Federated credential for custom OIDC provider"
displayName: custom-oidc-provider
issuer: "https://my-custom-oidc-provider.com"
subject: "service:my-application:environment:production"

Comments are disabled for this gist.