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

Managed Application Credentials #450

Closed

Conversation

dkistner
Copy link
Member

@dkistner dkistner commented May 20, 2022

How to categorize this PR?
/area security
/kind enhancement
/platform openstack

What this PR does / why we need it:
This PR adds support for application credentials managed by the Openstack extension.
The application credentials will be owned, created and deleted by the (technical) user which is provided by the Shoot owner.
All api calls to the Openstack layer will be made by the application credential, except the ones that are required to manage the application credential itself.

Using a managed application credential will help to not disrupt a cluster while the (technical) user of the cluster is exchanged, expired or its secret is rotated.

The application credential will be renewed after a configured lifetime during the next Shoot reconciliation/deletion operation. Even if the extension is unable the manage the application credential the application credential will be invalidated after a configured period via Openstack means.
The managed application credential usage is disabled by default and can be enabled via the controller config of the extension.

Which issue(s) this PR fixes:
Fixes #429

Special notes for your reviewer:
The following tasks need to be done fulfilled before this PR can be merged:

  • Feature documentation
  • Unit test coverage
  • End-to-end tests completed

The PR is opened as draft to start gathering feedback.
/invite @kon-angelo
/cc @donistz

Release note:

The `gardener-openstack-extension` can now manage an application credential which is used to call the Openstack layer instead of the (technical) user provided by the Shoot owner. The (technical) user will only be used to manage the application credential all other api calls to the Openstack layer will be done with the application credential. This will help to keep the Shoot functional when the technical user or its secret is rotated.

/squash

@gardener-robot gardener-robot added kind/api-change API change with impact on API users needs/second-opinion Needs second review by someone else labels May 20, 2022
@gardener-robot gardener-robot added area/security Security related kind/enhancement Enhancement, improvement, extension merge/squash Should be merged via 'Squash and merge' needs/review Needs review platform/openstack OpenStack platform/infrastructure size/xl Size of pull request is huge (see gardener-robot robot/bots/size.py) labels May 20, 2022
@gardener-robot-ci-2 gardener-robot-ci-2 added reviewed/ok-to-test Has approval for testing (check PR in detail before setting this label because PR is run on CI/CD) needs/ok-to-test Needs approval for testing (check PR in detail before setting this label because PR is run on CI/CD) and removed reviewed/ok-to-test Has approval for testing (check PR in detail before setting this label because PR is run on CI/CD) labels May 20, 2022
pkg/controller/infrastructure/add.go Show resolved Hide resolved
Comment on lines 82 to 92
if !appCredentialExists {
return m.removeApplicationCredentialStore(ctx, appCredential.secret)
}

if oldParentUserUsable {
if err := m.runGarbageCollection(ctx, oldParentUser, "", true); err != nil {
return err
}
}

return m.removeApplicationCredentialStore(ctx, appCredential.secret)
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe:

if appCredentialExists && oldParentUserUsable {
			if err := m.runGarbageCollection(ctx, oldParentUser, "", true); err != nil {
				return err
			}
}
return m.removeApplicationCredentialStore(ctx, appCredential.secret)

// application credential can be used. It will be tried to clean up with the
// old user if this one is usuable.
if newParentUser.isApplicationCredential() {
if appCredentialExists {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you need oldParentUsable check here too ? It seems similar to my previous comment so can they be consolidated e .g

if !m.config.Enabled  || newParentUser.isApplicationCredential()

Copy link
Member Author

Choose a reason for hiding this comment

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

Nice. Make sense.

Comment on lines 128 to 122
if parentChanged {
newAppCredential, err := m.createApplicationCredential(ctx, newParentUser)
if err != nil {
return err
}

// Try to delete the old application credential owned by the old user.
// This might not work as the information about this user could be stale,
// because the user credentials are rotated, the user is not associated to
// Openstack project anymore or it is deleted.
if err := oldParentUser.identityClient.DeleteApplicationCredential(ctx, oldParentUser.id, appCredential.id); err != nil {
m.logger.Error(err, "could not delete application credential as the owning user has changed and information about owning user might be stale")
}

return m.storeApplicationCredential(ctx, newAppCredential, newParentUser)
}

if m.isExpired(appCredential) {
newAppCredential, err := m.createApplicationCredential(ctx, newParentUser)
if err != nil {
return err
}

return m.storeApplicationCredential(ctx, newAppCredential, newParentUser)
}

return m.storeApplicationCredential(ctx, appCredential, newParentUser)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I get the feeling that the code can be condensed a bit more e.g.

if parentChanged || m.isExpired(appCredential) || !appCredentialExists {
		// Try to delete the old application credential owned by the old user.
		// This might not work as the information about this user could be stale,
		// because the user credentials are rotated, the user is not associated to
		// Openstack project anymore or it is deleted.
		if parentChanged{
				if err := oldParentUser.identityClient.DeleteApplicationCredential(ctx, oldParentUser.id, appCredential.id); err != nil {
			m.logger.Error(err, "could not delete application credential as the owning user has changed and information about owning user might be stale")
		         }
                }

		newAppCredential, err := m.createApplicationCredential(ctx, newParentUser)
		if err != nil {
			return err
		}
		if err :=  m.storeApplicationCredential(ctx, newAppCredential, newParentUser){
                    return err
                 }
}
if err := m.runGarbageCollection(ctx, newParentUser, appCredential.id, false); err != nil {
		return err
}

It is easy to miss a case anyway so I am not sure how big of an improvement it is.

}
}

func (m *Manager) runGarbageCollection(ctx context.Context, parent *parent, inUseAppCredentialID string, deleteInUseAppCredential bool) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

From the uses in actuator_delete and actuator_reconcile it is not clear to me if we need both inUseAppCredentialID and deleteInUseAppCredential. The general idea is to not delete the current in-use things and also have a mode where you delete everything. Isn't the same if you pass an empty in-use credential to delete everything ?

Copy link
Member Author

Choose a reason for hiding this comment

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

No we don't need both. It would be sufficient to pass the appCredentialID as a *string and check for nil. That's how I had it in the beginning and then changed to current version for better readability. Now I'm rather with you and changed is back.

@dkistner dkistner force-pushed the enh/managed-application-credentials branch from 119edf9 to bd7691c Compare June 24, 2022 07:47
@gardener-robot-ci-3 gardener-robot-ci-3 added reviewed/ok-to-test Has approval for testing (check PR in detail before setting this label because PR is run on CI/CD) and removed reviewed/ok-to-test Has approval for testing (check PR in detail before setting this label because PR is run on CI/CD) labels Jun 24, 2022
@dkistner dkistner force-pushed the enh/managed-application-credentials branch from bd7691c to bab9674 Compare June 24, 2022 07:52
@gardener-robot-ci-2 gardener-robot-ci-2 added reviewed/ok-to-test Has approval for testing (check PR in detail before setting this label because PR is run on CI/CD) and removed reviewed/ok-to-test Has approval for testing (check PR in detail before setting this label because PR is run on CI/CD) labels Jun 24, 2022
@gardener-robot
Copy link

@dkistner You need rebase this pull request with latest master branch. Please check.

@gardener-robot gardener-robot added the needs/rebase Needs git rebase label Aug 25, 2022
@dkistner
Copy link
Member Author

For the moment we will not continue with this PR. The extension and dependent components (mcm, ccm, csi etc.) are capable to work with application credentials. The lifecycle of the application credentials need for now be managed externally.

/close

@gardener-robot gardener-robot added the status/closed Issue is closed (either delivered or triaged) label Mar 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/security Security related kind/api-change API change with impact on API users kind/enhancement Enhancement, improvement, extension merge/squash Should be merged via 'Squash and merge' needs/ok-to-test Needs approval for testing (check PR in detail before setting this label because PR is run on CI/CD) needs/rebase Needs git rebase needs/review Needs review needs/second-opinion Needs second review by someone else platform/openstack OpenStack platform/infrastructure size/xl Size of pull request is huge (see gardener-robot robot/bots/size.py) status/closed Issue is closed (either delivered or triaged)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Managed application credentials
5 participants