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
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
apiVersion: cloudcredential.openshift.io/v1
kind: CredentialsRequest
metadata:
name: openshift-aws-cloud-controller-manager
namespace: openshift-cloud-credential-operator
annotations:
capability.openshift.io/name: CloudCredential+CloudControllerManager
include.release.openshift.io/self-managed-high-availability: "true"
include.release.openshift.io/single-node-developer: "true"
spec:
serviceAccountNames:
- cloud-controller-manager
secretRef:
name: cloud-controller-manager-credentials
namespace: openshift-cloud-controller-manager
cloudTokenPath: /var/run/secrets/openshift/serviceaccount/token
providerSpec:
apiVersion: cloudcredential.openshift.io/v1
kind: AWSProviderSpec
stsIAMRoleARN: ""
statementEntries:
- effect: Allow
action:
# Node lifecycle
- ec2:Describe*
- ec2:CreateSecurityGroup
- ec2:CreateTags
- ec2:DeleteSecurityGroup
- ec2:AuthorizeSecurityGroupIngress
- ec2:RevokeSecurityGroupIngress
- ec2:ModifyInstanceAttribute
# Volume management
- ec2:AttachVolume
- ec2:CreateVolume
- ec2:DeleteVolume
- ec2:DetachVolume
- ec2:ModifyVolume
- kms:DescribeKey
Comment on lines +33 to +38

@mfbonfigli mfbonfigli Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Volume mgmt perms are ported from master node IAM role in latest rev since they were also listed in the upstream AWS CCM docs, but it is likely that these permissions are actually unused by OpenShift CCM. A permission cleanup is out of scope for this PR for now.

# Load balancer management (CLB)
- elasticloadbalancing:AddTags
- elasticloadbalancing:AttachLoadBalancerToSubnets
- elasticloadbalancing:ApplySecurityGroupsToLoadBalancer
- elasticloadbalancing:CreateLoadBalancer
- elasticloadbalancing:CreateLoadBalancerPolicy
- elasticloadbalancing:CreateLoadBalancerListeners
- elasticloadbalancing:ConfigureHealthCheck
- elasticloadbalancing:DeleteLoadBalancer
- elasticloadbalancing:DeleteLoadBalancerListeners
- elasticloadbalancing:DeregisterInstancesFromLoadBalancer
- elasticloadbalancing:Describe*
- elasticloadbalancing:DetachLoadBalancerFromSubnets
- elasticloadbalancing:ModifyLoadBalancerAttributes
- elasticloadbalancing:RegisterInstancesWithLoadBalancer
- elasticloadbalancing:SetLoadBalancerPoliciesForBackendServer
- elasticloadbalancing:SetLoadBalancerPoliciesOfListener
# Load balancer management (NLB/ALB)
- elasticloadbalancing:CreateListener
- elasticloadbalancing:CreateTargetGroup
- elasticloadbalancing:DeleteListener
- elasticloadbalancing:DeleteTargetGroup
- elasticloadbalancing:DeregisterTargets
- elasticloadbalancing:ModifyListener
- elasticloadbalancing:ModifyTargetGroup
- elasticloadbalancing:ModifyTargetGroupAttributes
- elasticloadbalancing:RegisterTargets
# BYO Security Group for NLB
- elasticloadbalancing:SetSecurityGroups
resource: "*"
17 changes: 17 additions & 0 deletions pkg/cloud/aws/assets/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ spec:
env:
- name: CLOUD_CONFIG
value: /etc/kubernetes-cloud-config/cloud.conf
- name: AWS_SHARED_CREDENTIALS_FILE
value: /etc/aws-credentials/credentials
Comment on lines +57 to +58

@mfbonfigli mfbonfigli Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This variable is read automatically by the AWS SDK and takes precedence over master node IAM credentials retrieved via IMDS.

image: {{ .images.CloudControllerManager }}
imagePullPolicy: IfNotPresent
name: cloud-controller-manager
Expand All @@ -76,6 +78,12 @@ spec:
- name: trusted-ca
mountPath: /etc/pki/ca-trust/extracted/pem
readOnly: true
- name: aws-credentials
mountPath: /etc/aws-credentials
readOnly: true
- name: bound-sa-token
mountPath: /var/run/secrets/openshift/serviceaccount
readOnly: true
hostNetwork: true

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I left this one but maybe can it be dropped? Not sure if CCM needs the hostNetwork for something other than IMDS calls which should become obsolete with this PR. Asking for feedback on this one.

nodeSelector:
node-role.kubernetes.io/master: ""
Expand Down Expand Up @@ -123,3 +131,12 @@ spec:
hostPath:
path: /etc/kubernetes
type: Directory
- name: aws-credentials
secret:
secretName: cloud-controller-manager-credentials
- name: bound-sa-token
projected:
sources:
- serviceAccountToken:
path: token
audience: sts.amazonaws.com
31 changes: 31 additions & 0 deletions pkg/cloud/aws/aws_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"

configv1 "github.com/openshift/api/config/v1"

Expand Down Expand Up @@ -44,6 +47,34 @@ func TestResourcesRenderingSmoke(t *testing.T) {

resources := assets.GetRenderedResources()
assert.Len(t, resources, 3)

deploy, ok := resources[0].(*appsv1.Deployment)
require.True(t, ok, "first resource should be a Deployment")

container := deploy.Spec.Template.Spec.Containers[0]

assert.Contains(t, container.Env, corev1.EnvVar{
Name: "AWS_SHARED_CREDENTIALS_FILE",
Value: "/etc/aws-credentials/credentials",
})

assert.Contains(t, container.VolumeMounts, corev1.VolumeMount{
Name: "aws-credentials",
MountPath: "/etc/aws-credentials",
ReadOnly: true,
})
assert.Contains(t, container.VolumeMounts, corev1.VolumeMount{
Name: "bound-sa-token",
MountPath: "/var/run/secrets/openshift/serviceaccount",
ReadOnly: true,
})

volumeNames := make([]string, 0, len(deploy.Spec.Template.Spec.Volumes))
for _, v := range deploy.Spec.Template.Spec.Volumes {
volumeNames = append(volumeNames, v.Name)
}
assert.Contains(t, volumeNames, "aws-credentials")
assert.Contains(t, volumeNames, "bound-sa-token")
})
}
}