Authentication and Authorization
Relevant source files
The following files were used as context for generating this wiki page:
The authentication and authorization system in huskyCI is designed to secure the API and control access to its resources. It employs a two-tiered approach: Basic Authentication for administrative user actions and a repository-specific token system for CI/CD pipeline interactions.
This system ensures that only authenticated users can perform sensitive operations like generating or deactivating tokens, while analysis requests from pipelines are authorized on a per-repository basis. The core components include user validation via password hashing, and the generation, storage, and validation of repository access tokens.
User Authentication
User authentication is handled via HTTP Basic Authentication for a specific group of API endpoints. This mechanism is primarily used for administrative tasks such as managing repository tokens.
Sources: api/server.go:48-51
Basic Authentication Flow
The API server uses a middleware to enforce Basic Authentication on the /api/1.0 route group. The ValidateUser function is the core of this middleware.
The diagram below illustrates the sequence of events for a user authentication attempt.
Sources: api/auth/auth.go:16-36, api/server.go:51
Password Hashing
Passwords are not stored in plaintext. The system uses the PBKDF2 (Password-Based Key Derivation Function 2) algorithm for hashing and verification. The User data model stores the necessary components for this process.
The CheckPassword function orchestrates the verification by re-hashing the provided password with the stored salt and comparing the result with the stored hash.
Sources: api/auth/pbkdf2caller.go:13-20, api/types/types.go:73-81
User Data Structure
The User struct defines the schema for user data stored in the database, including credentials and PBKDF2 parameters.
| Field | Type | Description |
|---|---|---|
Username | string | The user's unique username. |
Password | string | The hashed password. |
Salt | string | Random data used as an additional input to the hash function. |
Iterations | int | The number of hash iterations to perform. |
KeyLen | int | The desired length of the derived key. |
HashFunction | string | The hash function used (e.g., sha512). |
NewPassword | string | Used temporarily when updating a password. Not stored. |
ConfirmNewPassword | string | Used temporarily for password confirmation. Not stored. |
Sources: api/types/types.go:73-81
Default User
Upon startup, huskyCI checks if a default user exists in the database. If not, it creates one using credentials provided via environment variables (HUSKYCI_API_DEFAULT_USERNAME and HUSKYCI_API_DEFAULT_PASSWORD). This ensures the system is immediately usable after a fresh deployment.
Sources: api/util/api/api.go:42-45, api/util/api/api.go:201-214
Repository Token System
For programmatic access, such as from a CI/CD pipeline, huskyCI uses repository-specific access tokens. A client must first authenticate using Basic Auth to obtain a token for a specific repository URL. This token is then used to authorize subsequent analysis requests for that repository.
Token Data Structures
The system uses several structs to manage tokens, from the initial request to their storage in the database.
| Struct | Purpose |
|---|---|
TokenRequest | JSON body for requesting a new token, containing the RepositoryURL. |
AccessToken | JSON response containing the newly generated HuskyToken. |
DBToken | The schema for storing token information in the database. |
Sources: api/types/types.go:167-187
The diagram below shows the entity relationship for the token data stored in the database.
Sources: api/types/types.go:179-187
Token Generation
A new token is generated via a POST request to the /api/1.0/token endpoint. The process is handled by the GenerateNewToken function.
The token generation flow is as follows:
- A new UUID is generated to uniquely identify the token record.
- A new salt is created.
- The token itself is generated as a random string.
- The token is hashed using the salt.
- The hashed token, along with its metadata (URL, validity, salt, UUID), is stored in the database.
- The plaintext token is returned to the client.
Sources: api/token/token.go:20-56, api/server.go:54
Token Deactivation
Tokens can be invalidated via a POST request to /api/1.0/token/deactivate. The DeactivateToken function finds the corresponding token in the database and sets its IsValid property to false. This effectively revokes the token without deleting the record.
Sources: api/token/token.go:58-70, api/server.go:55
Token Validation (Authorization)
When a client makes a request to start a new analysis, it must provide the repository URL and the corresponding huskyCI token. The CheckToken function validates this information.
- The function queries the database for a token associated with the provided repository URL.
- It checks if a token record was found.
- It verifies that the token's
IsValidflag istrue. - It hashes the token provided by the client using the salt from the database record.
- It compares the resulting hash with the hash stored in the database.
If all checks pass, the request is considered authorized.
Sources: api/token/tokenvalidator.go:17-43
API Endpoints Summary
The following table summarizes the API endpoints related to authentication and authorization.
| Endpoint | Method | Authentication | Description |
|---|---|---|---|
/api/1.0/token | POST | Basic Auth | Generates a new repository-specific access token. |
/api/1.0/token/deactivate | POST | Basic Auth | Deactivates an existing repository access token. |
/analysis | POST | huskyCI Token | Submits a repository for analysis, authorized by the token. |
Sources: api/server.go:51-60