Documentation
¶
Overview ¶
Package iam is a simple Authorization package based on the Google IAM (Identity and Access Management) Policy framework involves defining and managing access controls for resources.
This package does handles the identification / authn part of the IAM framework, as well as the Authorisation / Authz side of the framework. It authorises whether a particular **Principal** (user or service account) is able to perform a particular **Permission** (Get, Update, List, etc.) on a particular **Resource**. A resource is defined in the context of a Resource Driven development framework as defined at [RDD](https://google.com) inline with the [API Improvement Proposals](https://aip.dev)
Index ¶
- Constants
- type Authenticator
- func (h *Authenticator) ForwardAuthorizationHeader(ctx context.Context, allowMissingAuthHeader bool) (context.Context, error)
- func (h *Authenticator) HandleAuthRequest(resp http.ResponseWriter, req *http.Request)
- func (h *Authenticator) HandleNotFoundOrAccessDenied(resp http.ResponseWriter, req *http.Request)
- func (h *Authenticator) IsAuthRequest(req *http.Request) bool
- func (h *Authenticator) IsAuthenticated(resp http.ResponseWriter, req *http.Request) bool
- func (h *Authenticator) RedirectToSignIn(resp http.ResponseWriter, req *http.Request, postAuthRedirectUri string)
- type Authorizer
- func (a *Authorizer) AddIdentityPolicy()
- func (a *Authorizer) AddPolicy(policy *iampb.Policy)
- func (a *Authorizer) AddPolicyFromClientRpc(resource string, ...)
- func (a *Authorizer) AddPolicyFromServerRpc(resource string, ...)
- func (a *Authorizer) AsyncAddPolicy(resource string, fetchFunc func() *iampb.Policy)
- func (a *Authorizer) AuthorizeRpc() error
- func (a *Authorizer) HasAccess(permission string, policies ...*iampb.Policy) bool
- func (a *Authorizer) HasRole(policies []*iampb.Policy, role string) bool
- func (a *Authorizer) IsGroupMember(group string) bool
- func (a *Authorizer) Policies() []*iampb.Policy
- type BatchAuthorizer
- type IAM
- func (i *IAM) Disable()
- func (i *IAM) NewAuthorizer(ctx context.Context) (*Authorizer, context.Context, error)
- func (i *IAM) NewBatchAuthorizer(ctx context.Context) (*BatchAuthorizer, context.Context, error)
- func (s *IAM) RoleHasPermission(role string, permission string) bool
- func (s *IAM) WithMemberResolver(groupTypes []string, ...) *IAM
- type IamOption
- type IamOptions
- type Identity
- func (r *Identity) Accounts() map[string]*jwt.Account
- func (r *Identity) Email() string
- func (r *Identity) GroupIds() []string
- func (r *Identity) GroupNames() []string
- func (r *Identity) Id() string
- func (r *Identity) IsDeploymentServiceAccount() bool
- func (r *Identity) IsGoogleIdentity() bool
- func (r *Identity) IsServiceAccount() bool
- func (r *Identity) Jwt() string
- func (r *Identity) Policy() *iampb.Policy
- func (r *Identity) PolicyMember() string
- func (r *Identity) UserName() string
Constants ¶
const ( // One of the headers that cloudrun uses to send the JWT token of the authorized requester AuthHeader = "authorization" // One of the headers that cloudrun uses to send the JWT token of the authorized requester ServerlessAuthHeader = "x-serverless-authorization" // The header that this Alis Build package uses to forward the JWT token of the authorized requester AlisForwardingHeader = "x-alis-forwarded-authorization" // The header that Google Cloud ESPv2 proxy uses to forward the JWT token of the authorized requester ProxyForwardingHeader = "x-forwarded-authorization" // The header that Google Cloud IAP uses to forward the JWT token of the authorized requester IAPJWTAssertionHeader = "x-goog-iap-jwt-assertion" )
const ForwardedHostHeader = "x-forwarded-host"
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Authenticator ¶
type Authenticator struct {
// contains filtered or unexported fields
}
func NewAuthenticator ¶
func NewAuthenticator() *Authenticator
Creates a new Authenticator instance that can be used to authenticate users via the alis-build managed iam service.
func (*Authenticator) ForwardAuthorizationHeader ¶
func (h *Authenticator) ForwardAuthorizationHeader(ctx context.Context, allowMissingAuthHeader bool) (context.Context, error)
ForwardAuthorizationHeader forwards the Authorization header in the incoming ctx to the outgoing ctx. Use this at the very top of your unary and streaming interceptors in the context of a gRPC web server.
- ctx: the context
- allowMissingAuthHeader: whether to not return an error if the Authorization header is missing. Only set to true if you have checked for authentication when required in the http server layer and you have some methods that do not require authentication.
func (*Authenticator) HandleAuthRequest ¶
func (h *Authenticator) HandleAuthRequest(resp http.ResponseWriter, req *http.Request)
Reverse proxies to the authHost for all requests that have "/auth" as the prefix. You must first check if the request is an auth request using IsAuthRequest.
func (*Authenticator) HandleNotFoundOrAccessDenied ¶
func (h *Authenticator) HandleNotFoundOrAccessDenied(resp http.ResponseWriter, req *http.Request)
Reverse proxies to /auth/denied which shows a message in the line of "Not found or you don't have access".
func (*Authenticator) IsAuthRequest ¶
func (h *Authenticator) IsAuthRequest(req *http.Request) bool
Returns whether the request has "/auth" as the prefix.
func (*Authenticator) IsAuthenticated ¶
func (h *Authenticator) IsAuthenticated(resp http.ResponseWriter, req *http.Request) bool
Returns whether user is authenticated. First checks if there is a valid access token cookie and attaches it as an Authorization header. If above failed, it checks for a refresh_token cookie and tries to do a refresh on the fly by hitting /auth/refresh. Lastly, it checks directly for a Authorization header.
func (*Authenticator) RedirectToSignIn ¶
func (h *Authenticator) RedirectToSignIn(resp http.ResponseWriter, req *http.Request, postAuthRedirectUri string)
Redirects to /auth/signin and sets the post_auth_redirect_uri cookie to the current request URI so that the user can be redirected back after signing in.
- resp: the http.ResponseWriter
- req: the http.Request
- postAuthRedirectUri: where to go after signing in. Use req.RequestURI to redirect back to the current page.
type Authorizer ¶
type Authorizer struct {
// The Identity
Identity *Identity
// The rpc method
// Format: /package.service/method
Method string
// A generic cache that group resolvers can use to store data used to resolve group membership.
// There is no need to store final results in this cache, as these are automatically cached by the Authorizer.
// An example use case is to store the result of a database query to avoid duplicate queries if a query could
// resolve more than one group membership.
Cache *sync.Map
// contains filtered or unexported fields
}
Authorizer is responsible for the Authorization (i.e. Access) part of the IAM service and lives for the duration of a grpc method call. It is used to authorize the requester while providing access to the policy cache and the member cache to prevent redundant calls.
func (*Authorizer) AddIdentityPolicy ¶
func (a *Authorizer) AddIdentityPolicy()
AddIdentityPolicy adds a policy from the underlying Identity to the list of policies against which access will be validated. If the policy is not present in the Identity's jwt and a usersClient is provided, it will fetch the policy asynchronously. Will do nothing if identity is deployment service account or auth is already claimed. Auth is claimed if another method on this server is calling the method where this authorizer lives.
func (*Authorizer) AddPolicy ¶
func (a *Authorizer) AddPolicy(policy *iampb.Policy)
AddPolicy adds a policy to the list of policies against which any access will be validated. Do not add policies that should not be evaluated in downstream access checks. To add a policy that should only be evaluated for a specific access check, use the optional policies parameter in the HasAccess method. Will do nothing if identity is deployment service account or auth is already claimed. Auth is claimed if another method on this server is calling the method where this authorizer lives.
func (*Authorizer) AddPolicyFromClientRpc ¶
func (a *Authorizer) AddPolicyFromClientRpc(resource string, clientGetIamPolicyMethod func(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...grpc.CallOption) (*iampb.Policy, error))
Asynchronously fetches a policy on another server using a Grpc Client's GetIamPolicy method. Adds the fetched policy to the list of policies against which access will be validated. Will do nothing if identity is deployment service account or auth is already claimed. Auth is claimed if another method on this server is calling the method where this authorizer lives.
func (*Authorizer) AddPolicyFromServerRpc ¶
func (a *Authorizer) AddPolicyFromServerRpc(resource string, serverGetIamPolicyMethod func(ctx context.Context, req *iampb.GetIamPolicyRequest) (*iampb.Policy, error))
Asynchronously fetches a policy from a locally implemented service's GetIamPolicy method. Adds the fetched policy to the list of policies against which access will be validated. Will do nothing if identity is deployment service account or auth is already claimed. Auth is claimed if another method on this server is calling the method where this authorizer lives.
func (*Authorizer) AsyncAddPolicy ¶
func (a *Authorizer) AsyncAddPolicy(resource string, fetchFunc func() *iampb.Policy)
This function should rarely be used directly. Rather use the AddIdentityPolicy, AddPolicyFromClientRpc, or AddPolicyFromServerRpc functions. Asynchronously fetches a policy using the provided fetch function and adds it to the list of policies against which access will be validated.
func (*Authorizer) AuthorizeRpc ¶
func (a *Authorizer) AuthorizeRpc() error
AuthorizeRpc checks if the Identity has access to the current rpc method based on all the provided policies. This method returns an gRPC compliant error message and should be handled accordingly and is intented to be used by rpc methods.
func (*Authorizer) HasAccess ¶
func (a *Authorizer) HasAccess(permission string, policies ...*iampb.Policy) bool
HasAccess checks if the requester has access to the current method based on all the underlying policies as well as the optionally provided policies
func (*Authorizer) HasRole ¶
func (a *Authorizer) HasRole(policies []*iampb.Policy, role string) bool
Returns whether the requester has the specified role in the list of specified policies. Does not look in the Policies stored in the Authorizer, but rather the provided policies.
func (*Authorizer) IsGroupMember ¶
func (a *Authorizer) IsGroupMember(group string) bool
Returns whether identity is a member of the specified iam group.
func (*Authorizer) Policies ¶
func (a *Authorizer) Policies() []*iampb.Policy
Policies returns the list of policies against which any access will be validated.
type BatchAuthorizer ¶
type BatchAuthorizer struct {
// The Identity
Identity *Identity
// The rpc method
// Format: /package.service/method
Method string
// A generic cache that group resolvers can use to store data used to resolve group membership.
// There is no need to store final results in this cache, as these are automatically cached by the Authorizer.
// An example use case is to store the result of a database query to avoid duplicate queries if a query could
// resolve more than one group membership.
Cache *sync.Map
// contains filtered or unexported fields
}
func (*BatchAuthorizer) Authorizer ¶
func (b *BatchAuthorizer) Authorizer(resource string) *Authorizer
func (*BatchAuthorizer) CachePolicy ¶
func (b *BatchAuthorizer) CachePolicy(resource string, policy *iampb.Policy)
Adds a policy to the pool of cached policies. Authorizers created from this batch authorizer share this cache to avoid duplicate fetches. Not directly added to any authorizer's policies used to check access.
type IAM ¶
type IAM struct {
// the users client to use for fetching user policies in case they are not provided in the JWT token
UsersClient openIam.UsersServiceClient
// the users server to use for fetching user policies in case they are not provided in the JWT token
UsersServer openIam.UsersServiceServer
// contains filtered or unexported fields
}
A server authorizer is setup once per grpc server and contains static information about the roles, permissions and functions to resolve group memberships.
func New ¶
New creates a new IAM object. ALIS_OS_PROJECT environment variable must be set. ALIS_PRODUCT_CONFIG environment variable must be set if the product_config parameter is not set in Parameter Manager(https://console.cloud.google.com/security/parametermanager/locations/global/parameters/product_config).
func (*IAM) Disable ¶
func (i *IAM) Disable()
Disable removes any authentication checks across all Authorizers. Use this method for testing methods without enforcing authorization.
func (*IAM) NewAuthorizer ¶
NewAuthorizer creates a new authorizer which will live for the duration of the grpc method call.
It initializes an Authorizer with the provided IAM instance and performs the following actions:
- Identity Extraction: Extracts the Identity from the context, which includes information about the caller's authentication status and associated policies.
- Policy Initialization: If the extracted Identity has an associated policy, it is added to the Authorizer's list of policies.
- Super Admin Handling: Checks if the Identity represents a super admin. If so, authorization checks are skipped.
- Authorization Claiming: Marks the authorization as 'claimed' in the context to prevent redundant authorization checks within the same call. If the authorization is already claimed, it skips further checks.
- Method Extraction: Extracts the gRPC method name from the context, which is crucial for determining the required permissions. If the method cannot be extracted and the caller is not a super admin, it returns an error.
The resulting Authorizer is then returned, ready to be used for access control decisions.
Parameters:
ctx: The context containing information about the gRPC call, including the Identity and the method being invoked.
Returns:
- *Authorizer: A new Authorizer instance populated with the extracted Identity, method, and policies.
- error: An error if any of the extraction or initialization steps fail.
func (*IAM) NewBatchAuthorizer ¶
func (*IAM) RoleHasPermission ¶
RoleHasPermission check whether the specified role has the requested permission Arguments:
- role: the Role resource name, for example 'roles/admin', 'roles/report.viewer', etc.
- permission: the Permission, for example '/alis.in.reports.v1.ReportsService/GetReport'
func (*IAM) WithMemberResolver ¶
func (s *IAM) WithMemberResolver(groupTypes []string, resolver func(ctx context.Context, groupType string, groupId string, principal *Authorizer) bool) *IAM
WithMemberResolver registers a function to resolve whether a requester is a member of a group. There can be multiple different types of groups, e.g. "team:engineering" (groupType = "team",groupId="engineering") A group always has a type, but does not always have an id, e.g. "team:engineering" (groupType = "team",groupId="engineering") vs "all" (groupType = "all",groupId=""). "user" and "serviceAccounts" are not allowed as group types. "domain" is a builtin group type that is resolved by checking if the requester's email ends with the group id. Results are cached per Authorizer.
type IamOption ¶
type IamOption func(*IamOptions)
IamOption is a functional option for the New method.
func WithAdditionalSuperAdmins ¶
Sets the additional super admins. By default, only the deployment service account is a super admin. Arguments:
- superAdmins: the additional super admins e.g. 'user:<userId>', 'serviceAccount:<email>'
func WithUserServer ¶
func WithUserServer(userServer openIam.UsersServiceServer) IamOption
Should only be used by the alis managed users service. WithUserServer sets the user server to use for fetching user policies in case they are not provided in the JWT token. If set, the default users client is not used.
func WithoutDefaultUsersClient ¶
func WithoutDefaultUsersClient() IamOption
WithoutDefaultUsersClient disables the default users client which is normally called at "iam-users-{hash}.run.app:443" to fetch user policies in case they are not provided in the JWT token.
type IamOptions ¶
type IamOptions struct {
WithoutDefaultUsersClient bool
UserServer openIam.UsersServiceServer
SuperAdmins []string
}
IamOptions are the options for creating a new IAM object.
type Identity ¶
type Identity struct {
// contains filtered or unexported fields
}
Identity represents details on the entiry making the particular rpc request.
func ExtractIdentityFromCtx ¶
func ExtractIdentityFromCtx(ctx context.Context, deploymentServiceAccountEmail string, superAdmins map[string]bool) (*Identity, error)
ExtractIdentityFromCtx returns the Identity making the request or for whom the request is being forwarded by a super admin.
func (*Identity) GroupIds ¶
Returns the group Ids that the caller is part of Format: [{groupId}, ...]
func (*Identity) GroupNames ¶
Returns the groups that the caller is part of Format: [groups/{groupId}, ...]
func (*Identity) IsDeploymentServiceAccount ¶
func (*Identity) IsGoogleIdentity ¶
Returns whether the requester used a google identity to authenticate.
func (*Identity) IsServiceAccount ¶
Returns whether the requester is a service account.
func (*Identity) PolicyMember ¶
Returns the policy member string of the requester. E.g. user:123456789 or serviceAccount:alis-build@...