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

Scope various client requests to a project #44

Merged
merged 1 commit into from
Aug 1, 2024

Conversation

yankcrime
Copy link
Member

@yankcrime yankcrime commented Jul 31, 2024

The default API policies for OpenStack were amended almost unversally
(across projects) with the 2023.1 release to limit information returned
from client requests that are not scoped to a project, see the Glance
release notes for example:

https://docs.openstack.org/releasenotes/glance/2023.1.html#upgrade-notes

This commit introduces a new client that is scoped to a project and
updates the onboarding docs with the new OpenStack pre-reqs.

@yankcrime yankcrime requested a review from spjmurray July 31, 2024 12:20
Copy link

codecov bot commented Jul 31, 2024

Codecov Report

Attention: Patch coverage is 0% with 38 lines in your changes missing coverage. Please review.

Please upload report for BASE (main@efe2a38). Learn more about missing BASE report.

Files Patch % Lines
pkg/providers/openstack/client.go 0.00% 23 Missing ⚠️
pkg/providers/openstack/provider.go 0.00% 15 Missing ⚠️
Additional details and impacted files
@@          Coverage Diff           @@
##             main     #44   +/-   ##
======================================
  Coverage        ?   0.88%           
======================================
  Files           ?      27           
  Lines           ?    3834           
  Branches        ?       0           
======================================
  Hits            ?      34           
  Misses          ?    3796           
  Partials        ?       4           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@yankcrime yankcrime force-pushed the client_project_scoping branch 2 times, most recently from 22ac03a to ca39ad1 Compare July 31, 2024 13:46
@yankcrime yankcrime marked this pull request as ready for review July 31, 2024 13:48
@yankcrime yankcrime force-pushed the client_project_scoping branch 2 times, most recently from 6eefda3 to 42220e1 Compare July 31, 2024 13:59
@spjmurray
Copy link
Member

So why does this work for me...

diff --git a/charts/region/Chart.yaml b/charts/region/Chart.yaml
index 6021edd..1d02d6c 100644
--- a/charts/region/Chart.yaml
+++ b/charts/region/Chart.yaml
@@ -4,8 +4,8 @@ description: A Helm chart for deploying Unikorn's Region Controller
 
 type: application
 
-version: v0.1.29
-appVersion: v0.1.29
+version: v0.1.30
+appVersion: v0.1.30
 
 icon: https://raw.githubusercontent.com/unikorn-cloud/assets/main/images/logos/dark-on-light/icon.png
 
diff --git a/pkg/providers/openstack/client.go b/pkg/providers/openstack/client.go
index df86ee3..176e896 100644
--- a/pkg/providers/openstack/client.go
+++ b/pkg/providers/openstack/client.go
@@ -118,18 +118,8 @@ type DomainScopedPasswordProvider struct {
        domainID string
 }
 
-// ProjectScopedPasswordProvider allows use of an application credential.
-type ProjectScopedPasswordProvider struct {
-       endpoint    string
-       userID      string
-       password    string
-       projectName string
-       domainID    string
-}
-
 // Ensure the interface is implemented.
 var _ CredentialProvider = &DomainScopedPasswordProvider{}
-var _ CredentialProvider = &ProjectScopedPasswordProvider{}
 
 // NewDomainScopedPasswordProvider creates a client that consumes passwords
 // for authentication.
@@ -157,15 +147,25 @@ func (p *DomainScopedPasswordProvider) Client(ctx context.Context) (*gophercloud
        return authenticatedClient(ctx, options)
 }
 
+// ProjectScopedPasswordProvider allows use of an application credential.
+type ProjectScopedPasswordProvider struct {
+       endpoint  string
+       userID    string
+       password  string
+       projectID string
+}
+
+// Ensure the interface is implemented.
+var _ CredentialProvider = &ProjectScopedPasswordProvider{}
+
 // NewProjectScopedPasswordProvider creates a project-scoped client that consumes passwords
 // for authentication.
-func NewProjectScopedPasswordProvider(endpoint, userID, password, projectName, domainID string) *ProjectScopedPasswordProvider {
+func NewProjectScopedPasswordProvider(endpoint, userID, password, projectID string) *ProjectScopedPasswordProvider {
        return &ProjectScopedPasswordProvider{
-               endpoint:    endpoint,
-               userID:      userID,
-               password:    password,
-               projectName: projectName,
-               domainID:    domainID,
+               endpoint:  endpoint,
+               userID:    userID,
+               password:  password,
+               projectID: projectID,
        }
 }
 
@@ -176,8 +176,7 @@ func (p *ProjectScopedPasswordProvider) Client(ctx context.Context) (*gopherclou
                UserID:           p.userID,
                Password:         p.password,
                Scope: &gophercloud.AuthScope{
-                       DomainID:    p.domainID,
-                       ProjectName: p.projectName,
+                       ProjectID: p.projectID,
                },
                AllowReauth: true,
        }
diff --git a/pkg/providers/openstack/provider.go b/pkg/providers/openstack/provider.go
index bd645b1..795445f 100644
--- a/pkg/providers/openstack/provider.go
+++ b/pkg/providers/openstack/provider.go
@@ -61,10 +61,10 @@ type Provider struct {
        // secret is the current region secret.
        secret *corev1.Secret
 
-       domainID    string
-       projectName string
-       userID      string
-       password    string
+       domainID  string
+       projectID string
+       userID    string
+       password  string
 
        // DO NOT USE DIRECTLY, CALL AN ACCESSOR.
        _identity *IdentityClient
@@ -142,20 +142,24 @@ func (p *Provider) serviceClientRefresh(ctx context.Context) error {
                return fmt.Errorf("%w: password", ErrKeyUndefined)
        }
 
-       projectName, ok := secret.Data["project-name"]
+       projectID, ok := secret.Data["project-id"]
        if !ok {
                return fmt.Errorf("%w: project-id", ErrKeyUndefined)
        }
 
-       // Pass in an empty string to use the default project.
-       providerClient := NewProjectScopedPasswordProvider(region.Spec.Openstack.Endpoint, string(userID), string(password), string(projectName), string(domainID))
-
        // Create the clients.
+       // The identity client needs to have "manager" powers, so it create projects and
+       // users without full admin.
        identity, err := NewIdentityClient(ctx, NewDomainScopedPasswordProvider(region.Spec.Openstack.Endpoint, string(userID), string(password), string(domainID)))
        if err != nil {
                return err
        }
 
+       // Everything else gets the default view when bound to project, as domain scoped
+       // accesses do not work.  When provisioning in an identity's project, you will
+       // need to create a new scoped client
+       providerClient := NewProjectScopedPasswordProvider(region.Spec.Openstack.Endpoint, string(userID), string(password), string(projectID))
+
        compute, err := NewComputeClient(ctx, providerClient, region.Spec.Openstack.Compute)
        if err != nil {
                return err
@@ -176,7 +180,7 @@ func (p *Provider) serviceClientRefresh(ctx context.Context) error {
        p.secret = secret
 
        p.domainID = string(domainID)
-       p.projectName = string(projectName)
+       p.projectID = string(projectID)
 
        p.userID = string(userID)
        p.password = string(password)

and then run

openstack project create foo --domain unikorn-dev-simon
openstack role add --user unikorn-dev-simon --user-domain unikorn-dev-simon --project foo --project-domain unikorn-dev-simon member

and add the project ID to the secret? This is as I'd have expected, I'm not getting any unauthorized errors.

@yankcrime yankcrime force-pushed the client_project_scoping branch 2 times, most recently from 78c8636 to e61f543 Compare August 1, 2024 10:45
@yankcrime
Copy link
Member Author

Turns out the role assignment for the user I was testing with wasn't correctly specified, so have simplified this change.

@yankcrime yankcrime force-pushed the client_project_scoping branch 3 times, most recently from 1c61592 to 402f25f Compare August 1, 2024 10:53
Copy link
Member

@spjmurray spjmurray left a comment

Choose a reason for hiding this comment

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

Couple tweaks, plus I think you should run though the docs doing a copy & paste to make sure they work out of the box for other users who are less au fait with OpenStack

pkg/providers/openstack/README.md Show resolved Hide resolved
pkg/providers/openstack/README.md Outdated Show resolved Hide resolved
pkg/providers/openstack/README.md Show resolved Hide resolved
pkg/providers/openstack/client.go Show resolved Hide resolved
pkg/providers/openstack/provider.go Show resolved Hide resolved
@spjmurray
Copy link
Member

Also bump the version to v0.1.32... fast moving platform this!

The default API policies for OpenStack were amended almost unversally
(across projects) with the 2023.1 release to limit information returned
from client requests that are not scoped to a project, see the Glance
release notes for example:

https://docs.openstack.org/releasenotes/glance/2023.1.html#upgrade-notes
Copy link
Member

@spjmurray spjmurray left a comment

Choose a reason for hiding this comment

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

lgtm, plus I do actually need this for physical networks so I can bind the user to the project with advsvc!

@spjmurray spjmurray merged commit b4b82f1 into main Aug 1, 2024
2 checks passed
@spjmurray spjmurray deleted the client_project_scoping branch August 1, 2024 15:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants