go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/tokenserver/appengine/impl/projectscope/bigquery_log.go (about)

     1  // Copyright 2019 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 projectscope
    16  
    17  import (
    18  	"context"
    19  	"net"
    20  
    21  	"google.golang.org/protobuf/types/known/timestamppb"
    22  
    23  	"go.chromium.org/luci/auth/identity"
    24  
    25  	bqpb "go.chromium.org/luci/tokenserver/api/bq"
    26  	"go.chromium.org/luci/tokenserver/api/minter/v1"
    27  	"go.chromium.org/luci/tokenserver/appengine/impl/utils"
    28  	"go.chromium.org/luci/tokenserver/appengine/impl/utils/bq"
    29  )
    30  
    31  func init() {
    32  	bq.RegisterTokenKind("project_tokens", (*bqpb.ProjectToken)(nil))
    33  }
    34  
    35  // MintedTokenInfo is passed to LogToken.
    36  //
    37  // It carries all information about the token minting operation and the produced
    38  // token.
    39  type MintedTokenInfo struct {
    40  	Request      *minter.MintProjectTokenRequest  // RPC input, as is
    41  	Response     *minter.MintProjectTokenResponse // RPC output, as is
    42  	RequestedAt  *timestamppb.Timestamp
    43  	Expiration   *timestamppb.Timestamp
    44  	PeerIdentity identity.Identity // caller identity
    45  	PeerIP       net.IP            // caller IP address
    46  	RequestID    string            // GAE request ID that handled the RPC
    47  	AuthDBRev    int64             // revision of groups database (or 0 if unknown)
    48  }
    49  
    50  // toBigQueryMessage returns a message to upload to BigQuery.
    51  func (i *MintedTokenInfo) toBigQueryMessage() *bqpb.ProjectToken {
    52  	return &bqpb.ProjectToken{
    53  		// Information about the produced token.
    54  		Fingerprint:     utils.TokenFingerprint(i.Response.AccessToken),
    55  		ServiceAccount:  i.Response.ServiceAccountEmail,
    56  		OauthScopes:     i.Request.OauthScope,
    57  		LuciProject:     i.Request.LuciProject,
    58  		ServiceIdentity: i.PeerIdentity.Email(),
    59  		RequestedAt:     i.RequestedAt,
    60  		Expiration:      i.Expiration,
    61  		AuditTags:       i.Request.AuditTags,
    62  		PeerIp:          i.PeerIP.String(),
    63  		ServiceVersion:  i.Response.ServiceVersion,
    64  		GaeRequestId:    i.RequestID,
    65  		AuthDbRev:       i.AuthDBRev,
    66  	}
    67  }
    68  
    69  // TokenLogger records info about the token to BigQuery.
    70  type TokenLogger func(context.Context, *MintedTokenInfo) error
    71  
    72  // NewTokenLogger returns a callback that records info about tokens to BigQuery.
    73  //
    74  // Tokens themselves are not logged. Only first 16 bytes of their SHA256 hashes
    75  // (aka 'fingerprint') are. They are used only to identify tokens in logs.
    76  //
    77  // When dryRun is true, logs to the local text log only, not to BigQuery
    78  // (to avoid accidentally pushing fake data to real BigQuery dataset).
    79  func NewTokenLogger(dryRun bool) TokenLogger {
    80  	return func(ctx context.Context, i *MintedTokenInfo) error {
    81  		return bq.LogToken(ctx, i.toBigQueryMessage(), dryRun)
    82  	}
    83  }