go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/tokenserver/appengine/impl/serviceaccounts/bigquery_log.go (about) 1 // Copyright 2020 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package serviceaccounts 16 17 import ( 18 "context" 19 "net" 20 "time" 21 22 "google.golang.org/protobuf/types/known/timestamppb" 23 24 "go.chromium.org/luci/auth/identity" 25 26 bqpb "go.chromium.org/luci/tokenserver/api/bq" 27 "go.chromium.org/luci/tokenserver/api/minter/v1" 28 "go.chromium.org/luci/tokenserver/appengine/impl/utils" 29 "go.chromium.org/luci/tokenserver/appengine/impl/utils/bq" 30 ) 31 32 func init() { 33 bq.RegisterTokenKind("service_account_tokens", (*bqpb.ServiceAccountToken)(nil)) 34 } 35 36 // MintedTokenInfo is passed to LogToken. 37 // 38 // It carries all information about the token minting operation and the produced 39 // token. 40 type MintedTokenInfo struct { 41 Request *minter.MintServiceAccountTokenRequest // RPC input, as is 42 Response *minter.MintServiceAccountTokenResponse // RPC output, as is 43 RequestedAt time.Time 44 OAuthScopes []string // normalized list of requested OAuth scopes 45 RequestIdentity identity.Identity // identity used in authorization 46 PeerIdentity identity.Identity // identity of the direct peer 47 ConfigRev string // revision of the service config 48 PeerIP net.IP // caller's IP 49 RequestID string // GAE request ID that handles the RPC 50 AuthDBRev int64 // revision of the authorization database 51 } 52 53 // toBigQueryMessage returns a message to upload to BigQuery. 54 func (i *MintedTokenInfo) toBigQueryMessage() *bqpb.ServiceAccountToken { 55 return &bqpb.ServiceAccountToken{ 56 Fingerprint: utils.TokenFingerprint(i.Response.Token), 57 Kind: i.Request.TokenKind, 58 ServiceAccount: i.Request.ServiceAccount, 59 Realm: i.Request.Realm, 60 OauthScopes: i.OAuthScopes, 61 IdTokenAudience: i.Request.IdTokenAudience, 62 RequestIdentity: string(i.RequestIdentity), 63 PeerIdentity: string(i.PeerIdentity), 64 RequestedAt: timestamppb.New(i.RequestedAt), 65 Expiration: i.Response.Expiry, 66 AuditTags: i.Request.AuditTags, 67 ConfigRev: i.ConfigRev, 68 PeerIp: i.PeerIP.String(), 69 ServiceVersion: i.Response.ServiceVersion, 70 GaeRequestId: i.RequestID, 71 AuthDbRev: i.AuthDBRev, 72 } 73 } 74 75 // TokenLogger records info about the token to BigQuery. 76 type TokenLogger func(context.Context, *MintedTokenInfo) error 77 78 // NewTokenLogger returns a callback that records info about tokens to BigQuery. 79 // 80 // Tokens themselves are not logged. Only first 16 bytes of their SHA256 hashes 81 // (aka 'fingerprint') are. They are used only to identify tokens in logs. 82 // 83 // When dryRun is true, logs to the local text log only, not to BigQuery 84 // (to avoid accidentally pushing fake data to real BigQuery dataset). 85 func NewTokenLogger(dryRun bool) TokenLogger { 86 return func(ctx context.Context, i *MintedTokenInfo) error { 87 return bq.LogToken(ctx, i.toBigQueryMessage(), dryRun) 88 } 89 }