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

[ATB-150] Open API 3.0 Specs - TCP & UDP - Victor #70

Merged
merged 13 commits into from
Apr 10, 2023

Conversation

Victorblsilveira
Copy link
Collaborator

@Victorblsilveira Victorblsilveira commented Dec 6, 2022

Pull request checklist

  • Documentation updated?

Affected functionality

No functionality really affected, only documentation API Specs

Description of change

Adding UDS and TCP OpenAPI 3.0 Specs

Additional Stuff
VS Code Plugin for OpenAPI 3.0 Specs Security Checks, visualization, and much more:

@Victorblsilveira Victorblsilveira self-assigned this Dec 6, 2022
@mgbcaio mgbcaio changed the title Victor/atb 150 [DRAFT] Open API 3.0 Specs - TCP & UDP - Victor Dec 6, 2022
@mchurichi
Copy link
Member

Just to make sure I got APIs and responsibilities right, I'll try to recap and throw a few questions/doubts that came to my mind:
We have 4 personas here: Galadriel Admin (a.k.a. super user or box admin), Tenant Admin, Harvester, and Harvester Admin.

  • Galadriel Admin
    • is the one who onboards new tenants
    • do we want to let him/her manage tenant resources? (CRUD operations over members, fed groups, etc)
  • Tenant Admin
    • manages resources for a given tenant: onboards members, manage federation groups and requests memberships
    • do we want to let him/her manage harvester membership requests? (accept/deny requests)
  • Harvester
    • takes care of all bundle exchange related tasks: pushes it's colocated spire server bundle, and sets foreign bundles
  • Harvester Admin
    • is the one who -with the help of the Galadriel Admin- sets up the Harvester through the onboarding process
    • accepts/denies memberships requests

Given this, I wonder how we want to split our APIs. An API per persona? an API per transport protocol? We need to keep in mind that different methods (potentially in the same "API") may have different authorization mechanisms

@Victorblsilveira
Copy link
Collaborator Author

Just to make sure I got APIs and responsibilities right, I'll try to recap and throw a few questions/doubts that came to my mind: We have 4 personas here: Galadriel Admin (a.k.a. super user or box admin), Tenant Admin, Harvester, and Harvester Admin.

  • Galadriel Admin

    • is the one who onboards new tenants
    • do we want to let him/her manage tenant resources? (CRUD operations over members, fed groups, etc)
  • Tenant Admin

    • manages resources for a given tenant: onboards members, manage federation groups and requests memberships
    • do we want to let him/her manage harvester membership requests? (accept/deny requests)
  • Harvester

    • takes care of all bundle exchange related tasks: pushes it's colocated spire server bundle, and sets foreign bundles
  • Harvester Admin

    • is the one who -with the help of the Galadriel Admin- sets up the Harvester through the onboarding process
    • accepts/denies memberships requests

Given this, I wonder how we want to split our APIs. An API per persona? an API per transport protocol? We need to keep in mind that different methods (potentially in the same "API") may have different authorization mechanisms

I don't think that we should have APIs per persona since they can consume the same functionality. This is something that can be controlled through an authorization mechanism that we may consume. Initially, I would say to have one API for the TCP operations and another one for UDS. If we understand that is valid to split them ever further so we can do it, but for now I am not seeing a strong reason for that.

Copy link
Contributor

@maxlambrecht maxlambrecht left a comment

Choose a reason for hiding this comment

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

This is looking great, @Victorblsilveira !

I think we still need to put some thinking into which operations we need to accomplish the process of creating/registering a new Harvester. I left some thought about that and comments about other operations.

Do you plan to add the operation for adding a new tenant?

@Victorblsilveira
Copy link
Collaborator Author

This is looking great, @Victorblsilveira !

I think we still need to put some thinking into which operations we need to accomplish the process of creating/registering a new Harvester. I left some thought about that and comments about other operations.

Do you plan to add the operation for adding a new tenant?

Yes, I will add more endpoints to represent tenant operations. Tenant CRUD

Copy link
Contributor

@wibarre wibarre left a comment

Choose a reason for hiding this comment

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

For the transparency log validation, we need to add the signed-trust-bundle and the cert of the public key generated by Galadriel server.

@mchurichi
Copy link
Member

Just to summarize the thoughts I shared at yesterday's meeting: I think we need to be thoughtful on the permissions we give to admins. Allow admins to perform all CRUD operations over all resources just won't work, and it will cause more headaches than benefits (i.e. enable a tenant admin to update harvesters info could cause inconsistency issues, and even if we want to let them update some specific properties, we'd need to establish a granular permission system).

I emphasize the idea of continuing to focus on a clear definition of the personas, and the actions they would have to perform. This will help us think on the domain and the problem, and only then, drive the API design as a consequence.

@Victorblsilveira Victorblsilveira marked this pull request as ready for review January 12, 2023 13:01
@Victorblsilveira Victorblsilveira changed the title [DRAFT] Open API 3.0 Specs - TCP & UDP - Victor Open API 3.0 Specs - TCP & UDP - Victor Jan 13, 2023
@Victorblsilveira Victorblsilveira changed the title Open API 3.0 Specs - TCP & UDP - Victor [ATB-150] Open API 3.0 Specs - TCP & UDP - Victor Jan 17, 2023
@sonarqubecloud
Copy link

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

Copy link
Contributor

@jufantozzi jufantozzi left a comment

Choose a reason for hiding this comment

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

This is looking overall pretty good ⭐ great job @Victorblsilveira!

Most of comments are just minor fixes and trying to enforce consistency throughout the doc.

Copy link
Contributor

@maxlambrecht maxlambrecht left a comment

Choose a reason for hiding this comment

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

Thanks for this work, @Victorblsilveira. I left several comments, I think the main thing to be re-worked is the onboard, how the join_token is sent, and also explicitly define the formats of the certificates and trust bundles.

type: string
format: bytes
pattern: ^( *[A-Z0-9a-z] *.*)*$
maxLength: 400
Copy link
Contributor

Choose a reason for hiding this comment

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

Review

Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to look more in detail at this maxLenght? SPIRE stores up to 16Mb size trust bundles (in blobs in MYSQL). This is from the models.go in SPIRE: Data []byte gorm:"size:16777215" // make MySQL to use MEDIUMBLOB (max 16MB) - doesn't affect PostgreSQL/SQLite

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I was taking a look at the open API specification and maxLength is related to string length rather than size in bytes.
For restrictions in bytes size, we may need implementation reinforcement.

Copy link
Contributor

@maxlambrecht maxlambrecht left a comment

Choose a reason for hiding this comment

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

Hey @Victorblsilveira, these are the entities that are currently defined in Galadriel with the latest changes in the data model, do you think we can have those entities defined in this spec using the same fields and names?

type TrustDomain struct {
	ID                uuid.NullUUID
	Name              spiffeid.TrustDomain `json:"name"`
	Description       string               `json:"description"`
	HarvesterSpiffeID spiffeid.ID          `json:"harvester_spiffe_id"`
	OnboardingBundle  []byte               `json:"onboarding_bundle"`
	CreatedAt         time.Time            `json:"created_at"`
	UpdatedAt         time.Time            `json:"updated_at"`
}

type Relationship struct {
	ID                  uuid.NullUUID
	TrustDomainAID      uuid.UUID            `json:"trust_domain_a_id"`
	TrustDomainBID      uuid.UUID            `json:"trust_domain_b_id"`
	TrustDomainAName    spiffeid.TrustDomain `json:"trust_domain_a_name"`
	TrustDomainBName    spiffeid.TrustDomain `json:"trust_domain_b_name"`
	TrustDomainAConsent bool                 `json:"trust_domain_a_consent"`
	TrustDomainBConsent bool                 `json:"trust_domain_b_consent"`
	CreatedAt           time.Time            `json:"created_at"`
	UpdatedAt           time.Time            `json:"updated_at"`
}

type JoinToken struct {
	ID              uuid.NullUUID
	Token           string
	Used            bool
	TrustDomainID   uuid.UUID            `json:"trust_domain_id"`
	TrustDomainName spiffeid.TrustDomain `json:"trust_domain_name"`
	ExpiresAt       time.Time            `json:"expires_at"`
	CreatedAt       time.Time            `json:"created_at"`
	UpdatedAt       time.Time            `json:"updated_at"`
}

// Bundle represents a SPIFFE Trust bundle along with its digest.
type Bundle struct {
	ID                 uuid.NullUUID
	Data               []byte               `json:"bundle"`
	Digest             []byte               `json:"bundle_digest"`
	Signature          []byte               `json:"signature"`
	DigestAlgorithm    string               `json:"digest_algorithm"`
	SignatureAlgorithm string               `json:"signature_algorithm"`
	SigningCert        []byte               `json:"signing_cert"`
	TrustDomainID      uuid.UUID            `json:"trust_domain_id"`
	TrustDomainName    spiffeid.TrustDomain `json:"trust_domain_name"`
	CreatedAt          time.Time            `json:"created_at"`
	UpdatedAt          time.Time            `json:"updated_at"`
}

@Victorblsilveira
Copy link
Collaborator Author

with the latest changes i

That is a great idea. Not sure if will be possible to have a 1:1 mapping in the open API spec due to some limitations in the specification but it is worth trying.

Copy link
Contributor

@wibarre wibarre left a comment

Choose a reason for hiding this comment

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

Great job Victor. Thanks for working on this. I focused mainly in the management.yaml. The mechanics of the comms between harvester and server is being worked on, so I am waiting to hear what the outcome is from that front.

type: string
format: bytes
pattern: ^( *[A-Z0-9a-z] *.*)*$
maxLength: 400
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to look more in detail at this maxLenght? SPIRE stores up to 16Mb size trust bundles (in blobs in MYSQL). This is from the models.go in SPIRE: Data []byte gorm:"size:16777215" // make MySQL to use MEDIUMBLOB (max 16MB) - doesn't affect PostgreSQL/SQLite

type: string
format: byte
pattern: ^( *[A-Z0-9a-z] *.*)*$
maxLength: 65
Copy link
Member

Choose a reason for hiding this comment

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

64 bytes are enough to fit the most common hashing algorithms up to 512 bits (SHA-512, SHA3-512)

JWT:
type: string
format: uuid
maxLength: 4096 # Number of characters
Copy link
Member

Choose a reason for hiding this comment

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

where does this max length come from?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

JWT specification does not have a max length limit. Although usually, JWT tokens are stored in session cookies or HTTP header who has limits around 4096 and 8192 respectively. We can leave it open if you see that does make sense to limit it.

Copy link
Contributor

Choose a reason for hiding this comment

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

+1 for using 8192

state:
type: array
items:
$ref: '#/components/schemas/TrustBundleSync'
Copy link
Member

Choose a reason for hiding this comment

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

could you please sync with @jufantozzi on what should be in both updates and state here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I spoke with @jufantozzi (correct me if I am wrong) regarding this. The conclusion was, for now, the changes regarding if we are going to send the consent signature alongside the bundles, need a design discussion.

Copy link
Member

Choose a reason for hiding this comment

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

Ok, that makes sense, but still, and AFAIK updates and state shouldn't have the same structure.
state holds the digests of ALL the bundles a Harvester knows about.
updates holds all the NEW bundles a Harvester needs to set in SPIRE.

With @jufantozzi we worked on a flow breakdown doc a while ago, it may be a bit outdated though.

Copy link
Contributor

Choose a reason for hiding this comment

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

updates and state shouldn't have the same structure. state holds the digests of ALL the bundles a Harvester knows about. updates holds all the NEW bundles a Harvester needs to set in SPIRE.

This is correct.

Copy link
Contributor

Choose a reason for hiding this comment

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

The conclusion was, for now, the changes regarding if we are going to send the consent signature alongside the bundles, need a design discussion.

This is another discussion, in the new bundles (so in updates) each bundle will come with a consent, but this is still TBD.

Copy link
Contributor

@jufantozzi jufantozzi Mar 21, 2023

Choose a reason for hiding this comment

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

We missed that the object for responses were the same, they shouldn't be. One maps trust-domains to digests, and the other maps trust-domains to bundles. I lead to this confusion because I missed this and thought you're talking about something else @mchurichi 😓 my bad

Copy link
Member

@mchurichi mchurichi left a comment

Choose a reason for hiding this comment

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

Just a suggestion for the sake of the review process: could you please wait until pushing the changes to mark a comment as resolved? Sometimes, I just don't know if a comment went stale or was discarded, and sometimes I doubt whether or not I made the suggestion I meant to 😆

Copy link
Contributor

@wibarre wibarre left a comment

Choose a reason for hiding this comment

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

Thank you Victor for the great work.

doc/API.md Outdated
Comment on lines 30 to 31
2.1 While in the [management](../pkg/server/api/management/) directory, run the following command:
- `oapi-codegen -config management.cfg.yaml management.yaml`
Copy link
Member

Choose a reason for hiding this comment

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

update to use admin instead of management

example: "trust.domain.com"
BundleDigest:
type: string
format: byte
Copy link
Member

Choose a reason for hiding this comment

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

Same thing as trust bundle format.

The hashing algorithms can output a short set of characters we can easily handle as simple strings. If we want to store it as bytes (I don't see a reason to do so) we should have them base-64-encoded, and the example above needs to be changed accordingly.

I'll just remove the format for now.

-----END CERTIFICATE-----
Signature:
type: string
format: byte
Copy link
Member

Choose a reason for hiding this comment

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

same

Comment on lines 39 to 40
- onboarding_bundle
- harvester_spiffe_id
Copy link
Member

Choose a reason for hiding this comment

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

remove these, please

Comment on lines 97 to 102
- name: status
in: query
schema:
type: string
enum: [approved, denied, pending]
default: pending
Copy link
Member

Choose a reason for hiding this comment

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

Are we allowing filtering by multiple statuses at the same time? it feels like we should.
Also, it would be more user-friendly to have a default value that returns all values rather than filtering the results at all.

type: array
items:
$ref: '../../../common/api/schemas.yaml#/components/schemas/Relationship'
maxItems: 100
Copy link
Member

Choose a reason for hiding this comment

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

I'd suggest to remove this for now until we implement some sort of pagination.

wibarre
wibarre previously approved these changes Apr 7, 2023
Copy link
Contributor

@wibarre wibarre left a comment

Choose a reason for hiding this comment

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

Thank you Victor for retrofitting all the feedback into this PR.

@sonarqubecloud
Copy link

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

Copy link
Contributor

@maxlambrecht maxlambrecht left a comment

Choose a reason for hiding this comment

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

Excellent work @Victorblsilveira!

Copy link
Member

@mchurichi mchurichi left a comment

Choose a reason for hiding this comment

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

🙌

@Victorblsilveira Victorblsilveira merged commit 76e0395 into main Apr 10, 2023
@Victorblsilveira Victorblsilveira deleted the victor/atb-150 branch April 10, 2023 14:40
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.

6 participants