feat: audit oauth2 app management (#12275)

* Audit oauth2 app management
* Use 201 for creating secrets
This commit is contained in:
Asher
2024-02-26 15:52:08 -08:00
committed by GitHub
parent 6b866b3f48
commit f74532ff50
16 changed files with 212 additions and 59 deletions

8
coderd/apidoc/docs.go generated
View File

@ -11504,7 +11504,9 @@ const docTemplate = `{
"convert_login",
"health_settings",
"workspace_proxy",
"organization"
"organization",
"oauth2_provider_app",
"oauth2_provider_app_secret"
],
"x-enum-varnames": [
"ResourceTypeTemplate",
@ -11519,7 +11521,9 @@ const docTemplate = `{
"ResourceTypeConvertLogin",
"ResourceTypeHealthSettings",
"ResourceTypeWorkspaceProxy",
"ResourceTypeOrganization"
"ResourceTypeOrganization",
"ResourceTypeOAuth2ProviderApp",
"ResourceTypeOAuth2ProviderAppSecret"
]
},
"codersdk.Response": {

View File

@ -10378,7 +10378,9 @@
"convert_login",
"health_settings",
"workspace_proxy",
"organization"
"organization",
"oauth2_provider_app",
"oauth2_provider_app_secret"
],
"x-enum-varnames": [
"ResourceTypeTemplate",
@ -10393,7 +10395,9 @@
"ResourceTypeConvertLogin",
"ResourceTypeHealthSettings",
"ResourceTypeWorkspaceProxy",
"ResourceTypeOrganization"
"ResourceTypeOrganization",
"ResourceTypeOAuth2ProviderApp",
"ResourceTypeOAuth2ProviderAppSecret"
]
},
"codersdk.Response": {

View File

@ -333,6 +333,22 @@ func (api *API) auditLogIsResourceDeleted(ctx context.Context, alog database.Get
api.Logger.Error(ctx, "unable to fetch workspace", slog.Error(err))
}
return workspace.Deleted
case database.ResourceTypeOauth2ProviderApp:
_, err := api.Database.GetOAuth2ProviderAppByID(ctx, alog.ResourceID)
if xerrors.Is(err, sql.ErrNoRows) {
return true
} else if err != nil {
api.Logger.Error(ctx, "unable to fetch oauth2 app", slog.Error(err))
}
return false
case database.ResourceTypeOauth2ProviderAppSecret:
_, err := api.Database.GetOAuth2ProviderAppSecretByID(ctx, alog.ResourceID)
if xerrors.Is(err, sql.ErrNoRows) {
return true
} else if err != nil {
api.Logger.Error(ctx, "unable to fetch oauth2 app secret", slog.Error(err))
}
return false
default:
return false
}
@ -379,6 +395,16 @@ func (api *API) auditLogResourceLink(ctx context.Context, alog database.GetAudit
return fmt.Sprintf("/@%s/%s/builds/%s",
workspaceOwner.Username, additionalFields.WorkspaceName, additionalFields.BuildNumber)
case database.ResourceTypeOauth2ProviderApp:
return fmt.Sprintf("/deployment/oauth2-provider/apps/%s", alog.ResourceID)
case database.ResourceTypeOauth2ProviderAppSecret:
secret, err := api.Database.GetOAuth2ProviderAppSecretByID(ctx, alog.ResourceID)
if err != nil {
return ""
}
return fmt.Sprintf("/deployment/oauth2-provider/apps/%s", secret.AppID)
default:
return ""
}

View File

@ -19,7 +19,9 @@ type Auditable interface {
database.License |
database.WorkspaceProxy |
database.AuditOAuthConvertState |
database.HealthSettings
database.HealthSettings |
database.OAuth2ProviderApp |
database.OAuth2ProviderAppSecret
}
// Map is a map of changed fields in an audited resource. It maps field names to

View File

@ -99,6 +99,10 @@ func ResourceTarget[T Auditable](tgt T) string {
return string(typed.ToLoginType)
case database.HealthSettings:
return "" // no target?
case database.OAuth2ProviderApp:
return typed.Name
case database.OAuth2ProviderAppSecret:
return typed.DisplaySecret
default:
panic(fmt.Sprintf("unknown resource %T for ResourceTarget", tgt))
}
@ -132,6 +136,10 @@ func ResourceID[T Auditable](tgt T) uuid.UUID {
case database.HealthSettings:
// Artificial ID for auditing purposes
return typed.ID
case database.OAuth2ProviderApp:
return typed.ID
case database.OAuth2ProviderAppSecret:
return typed.ID
default:
panic(fmt.Sprintf("unknown resource %T for ResourceID", tgt))
}
@ -163,6 +171,10 @@ func ResourceType[T Auditable](tgt T) database.ResourceType {
return database.ResourceTypeConvertLogin
case database.HealthSettings:
return database.ResourceTypeHealthSettings
case database.OAuth2ProviderApp:
return database.ResourceTypeOauth2ProviderApp
case database.OAuth2ProviderAppSecret:
return database.ResourceTypeOauth2ProviderAppSecret
default:
panic(fmt.Sprintf("unknown resource %T for ResourceType", typed))
}
@ -195,6 +207,10 @@ func ResourceRequiresOrgID[T Auditable]() bool {
case database.HealthSettings:
// Artificial ID for auditing purposes
return false
case database.OAuth2ProviderApp:
return false
case database.OAuth2ProviderAppSecret:
return false
default:
panic(fmt.Sprintf("unknown resource %T for ResourceRequiresOrgID", tgt))
}

View File

@ -135,7 +135,9 @@ CREATE TYPE resource_type AS ENUM (
'license',
'workspace_proxy',
'convert_login',
'health_settings'
'health_settings',
'oauth2_provider_app',
'oauth2_provider_app_secret'
);
CREATE TYPE startup_script_behavior AS ENUM (

View File

@ -0,0 +1,2 @@
-- It is not possible to drop enum values from enum types, so the UPs on
-- resource_type have "IF NOT EXISTS".

View File

@ -0,0 +1,2 @@
ALTER TYPE resource_type ADD VALUE IF NOT EXISTS 'oauth2_provider_app';
ALTER TYPE resource_type ADD VALUE IF NOT EXISTS 'oauth2_provider_app_secret';

View File

@ -1149,19 +1149,21 @@ func AllProvisionerTypeValues() []ProvisionerType {
type ResourceType string
const (
ResourceTypeOrganization ResourceType = "organization"
ResourceTypeTemplate ResourceType = "template"
ResourceTypeTemplateVersion ResourceType = "template_version"
ResourceTypeUser ResourceType = "user"
ResourceTypeWorkspace ResourceType = "workspace"
ResourceTypeGitSshKey ResourceType = "git_ssh_key"
ResourceTypeApiKey ResourceType = "api_key"
ResourceTypeGroup ResourceType = "group"
ResourceTypeWorkspaceBuild ResourceType = "workspace_build"
ResourceTypeLicense ResourceType = "license"
ResourceTypeWorkspaceProxy ResourceType = "workspace_proxy"
ResourceTypeConvertLogin ResourceType = "convert_login"
ResourceTypeHealthSettings ResourceType = "health_settings"
ResourceTypeOrganization ResourceType = "organization"
ResourceTypeTemplate ResourceType = "template"
ResourceTypeTemplateVersion ResourceType = "template_version"
ResourceTypeUser ResourceType = "user"
ResourceTypeWorkspace ResourceType = "workspace"
ResourceTypeGitSshKey ResourceType = "git_ssh_key"
ResourceTypeApiKey ResourceType = "api_key"
ResourceTypeGroup ResourceType = "group"
ResourceTypeWorkspaceBuild ResourceType = "workspace_build"
ResourceTypeLicense ResourceType = "license"
ResourceTypeWorkspaceProxy ResourceType = "workspace_proxy"
ResourceTypeConvertLogin ResourceType = "convert_login"
ResourceTypeHealthSettings ResourceType = "health_settings"
ResourceTypeOauth2ProviderApp ResourceType = "oauth2_provider_app"
ResourceTypeOauth2ProviderAppSecret ResourceType = "oauth2_provider_app_secret"
)
func (e *ResourceType) Scan(src interface{}) error {
@ -1213,7 +1215,9 @@ func (e ResourceType) Valid() bool {
ResourceTypeLicense,
ResourceTypeWorkspaceProxy,
ResourceTypeConvertLogin,
ResourceTypeHealthSettings:
ResourceTypeHealthSettings,
ResourceTypeOauth2ProviderApp,
ResourceTypeOauth2ProviderAppSecret:
return true
}
return false
@ -1234,6 +1238,8 @@ func AllResourceTypeValues() []ResourceType {
ResourceTypeWorkspaceProxy,
ResourceTypeConvertLogin,
ResourceTypeHealthSettings,
ResourceTypeOauth2ProviderApp,
ResourceTypeOauth2ProviderAppSecret,
}
}