// Copyright 2016 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package authdb

import (
	"context"
	"io"
	"net"

	"github.com/golang/protobuf/proto"
	"go.opentelemetry.io/otel/attribute"

	"go.chromium.org/luci/auth/identity"
	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/common/logging"

	"go.chromium.org/luci/server/auth/authdb/internal/certs"
	"go.chromium.org/luci/server/auth/authdb/internal/graph"
	"go.chromium.org/luci/server/auth/authdb/internal/ipaddr"
	"go.chromium.org/luci/server/auth/authdb/internal/oauthid"
	"go.chromium.org/luci/server/auth/authdb/internal/realmset"
	"go.chromium.org/luci/server/auth/authdb/internal/seccfg"
	"go.chromium.org/luci/server/auth/internal/tracing"
	"go.chromium.org/luci/server/auth/realms"
	"go.chromium.org/luci/server/auth/service/protocol"
	"go.chromium.org/luci/server/auth/signing"
)

// SnapshotDB implements DB using AuthDB proto message.
//
// Use NewSnapshotDB to create new instances. Don't touch public fields
// of existing instances.
//
// Zero value represents an empty AuthDB.
type SnapshotDB struct {
	AuthServiceURL string // where it was fetched from
	Rev            int64  // its revision number

	groups         *graph.QueryableGraph  // queryable representation of groups
	realms         *realmset.Realms       // queryable representation of realms
	clientIDs      oauthid.Allowlist      // set of allowed client IDs
	allowlistedIPs ipaddr.Allowlist       // set of named IP allowlist
	securityCfg    *seccfg.SecurityConfig // parsed SecurityConfig proto

	tokenServiceURL   string       // URL of the token server as provided by Auth service
	tokenServiceCerts certs.Bundle // cached public keys of the token server
}

var _ DB = &SnapshotDB{}

// Revision returns a revision of an auth DB or 0 if it can't be determined.
//
// It's just a small helper that casts db to *SnapshotDB and extracts the
// revision from there.
func Revision(db DB) int64 {
	if snap, _ := db.(*SnapshotDB); snap != nil {
		return snap.Rev
	}
	return 0
}

// SnapshotDBFromTextProto constructs SnapshotDB by loading it from a text proto
// with AuthDB message.
func SnapshotDBFromTextProto(r io.Reader) (*SnapshotDB, error) {
	blob, err := io.ReadAll(r)
	if err != nil {
		return nil, errors.Annotate(err, "failed to read the file").Err()
	}
	msg := &protocol.AuthDB{}
	if err := proto.UnmarshalText(string(blob), msg); err != nil {
		return nil, errors.Annotate(err, "not a valid AuthDB text proto file").Err()
	}
	db, err := NewSnapshotDB(msg, "", 0, true)
	if err != nil {
		return nil, errors.Annotate(err, "failed to validate AuthDB").Err()
	}
	return db, nil
}

// NewSnapshotDB creates new instance of SnapshotDB.
//
// It does some preprocessing to speed up subsequent checks. Returns errors if
// it encounters inconsistencies.
//
// If 'validate' is false, skips some expensive validation steps, assuming they
// were performed before, when AuthDB was initially received.
func NewSnapshotDB(authDB *protocol.AuthDB, authServiceURL string, rev int64, validate bool) (*SnapshotDB, error) {
	if validate {
		if err := validateAuthDB(authDB); err != nil {
			return nil, err
		}
	}

	groups, err := graph.BuildQueryable(authDB.Groups)
	if err != nil {
		return nil, errors.Annotate(err, "failed to build groups graph").Err()
	}

	var realmSet *realmset.Realms
	if authDB.Realms != nil {
		realmSet, err = realmset.Build(authDB.Realms, groups, realms.RegisteredPermissions())
		if err != nil {
			return nil, errors.Annotate(err, "failed to prepare Realms DB").Err()
		}
	}

	allowlistedIPs, err := ipaddr.NewAllowlist(authDB.IpWhitelists, authDB.IpWhitelistAssignments)
	if err != nil {
		return nil, errors.Annotate(err, "bad IP allowlist in AuthDB").Err()
	}

	securityCfg, err := seccfg.Parse(authDB.SecurityConfig)
	if err != nil {
		return nil, errors.Annotate(err, "bad SecurityConfig").Err()
	}

	return &SnapshotDB{
		AuthServiceURL:    authServiceURL,
		Rev:               rev,
		groups:            groups,
		realms:            realmSet,
		clientIDs:         oauthid.NewAllowlist(authDB.OauthClientId, authDB.OauthAdditionalClientIds),
		allowlistedIPs:    allowlistedIPs,
		securityCfg:       securityCfg,
		tokenServiceURL:   authDB.TokenServerUrl,
		tokenServiceCerts: certs.Bundle{ServiceURL: authDB.TokenServerUrl},
	}, nil
}

// IsAllowedOAuthClientID returns true if the given OAuth2 client ID can be used
// to authorize access from the given email.
func (db *SnapshotDB) IsAllowedOAuthClientID(_ context.Context, email, clientID string) (bool, error) {
	return db.clientIDs.IsAllowedOAuthClientID(email, clientID), nil
}

// IsInternalService returns true if the given hostname belongs to a service
// that is a part of the current LUCI deployment.
//
// What hosts are internal is controlled by 'internal_service_regexp' setting
// in security.cfg in the Auth Service configs.
func (db *SnapshotDB) IsInternalService(ctx context.Context, hostname string) (bool, error) {
	if db.securityCfg != nil {
		return db.securityCfg.IsInternalService(hostname), nil
	}
	return false, nil
}

// IsMember returns true if the given identity belongs to any of the groups.
//
// Unknown groups are considered empty, but are logged as warnings.
// May return errors if underlying datastore has issues.
func (db *SnapshotDB) IsMember(ctx context.Context, id identity.Identity, groups []string) (ok bool, err error) {
	_, span := tracing.Start(ctx, "go.chromium.org/luci/server/auth/authdb.IsMember",
		attribute.StringSlice("cr.dev.groups", groups),
	)
	defer func() { tracing.End(span, err, attribute.Bool("cr.dev.outcome", ok)) }()

	if db.groups == nil {
		return false, nil
	}

	// TODO(vadimsh): Optimize multi-group case.
	for _, gr := range groups {
		switch db.groups.IsMember(id, gr) {
		case graph.IdentIsMember:
			return true, nil
		case graph.GroupIsUnknown:
			logging.Warningf(ctx, "Group %q is unknown in auth db snapshot %d", gr, db.Rev)
		}
	}
	return false, nil
}

// CheckMembership returns groups from the given list the identity belongs to.
//
// Unlike IsMember, it doesn't stop on the first hit but continues evaluating
// all groups.
//
// Unknown groups are considered empty. The order of groups in the result may
// be different from the order in 'groups'.
//
// May return errors if underlying datastore has issues.
func (db *SnapshotDB) CheckMembership(ctx context.Context, id identity.Identity, groups []string) (out []string, err error) {
	_, span := tracing.Start(ctx, "go.chromium.org/luci/server/auth/authdb.CheckMembership",
		attribute.StringSlice("cr.dev.groups", groups),
	)
	defer func() { tracing.End(span, err, attribute.StringSlice("cr.dev.outcome", out)) }()

	if db.groups == nil {
		return
	}

	// TODO(vadimsh): Optimize multi-group case.
	for _, gr := range groups {
		switch db.groups.IsMember(id, gr) {
		case graph.IdentIsMember:
			out = append(out, gr)
		case graph.GroupIsUnknown:
			logging.Warningf(ctx, "Group %q is unknown in auth db snapshot %d", gr, db.Rev)
		}
	}
	return
}

// HasPermission returns true if the identity has the given permission in the
// realm.
func (db *SnapshotDB) HasPermission(ctx context.Context, id identity.Identity, perm realms.Permission, realm string, attrs realms.Attrs) (ok bool, err error) {
	otelAttrs := append(make([]attribute.KeyValue, 0, 2+len(attrs)),
		attribute.String("cr.dev.permission", perm.Name()),
		attribute.String("cr.dev.realm", realm),
	)
	for k, v := range attrs {
		otelAttrs = append(otelAttrs, attribute.String("cr.dev.attr."+k, v))
	}
	ctx, span := tracing.Start(ctx, "go.chromium.org/luci/server/auth/authdb.HasPermission",
		otelAttrs...,
	)
	defer func() { tracing.End(span, err, attribute.Bool("cr.dev.outcome", ok)) }()

	// This may happen if the AuthDB proto has no Realms yet.
	if db.realms == nil {
		return false, errors.Reason("Realms API is not available").Err()
	}

	permIdx, ok := db.realms.PermissionIndex(perm)
	if !ok {
		logging.Warningf(ctx, "Checking permission %q not present in the AuthDB", perm)
		return false, nil
	}

	// Verify such realm is defined in the DB or fallback to its @root.
	if !db.realms.HasRealm(realm) {
		if err := realms.ValidateRealmName(realm, realms.GlobalScope); err != nil {
			return false, errors.Annotate(err, "when checking %q", perm).Err()
		}
		project, name := realms.Split(realm)
		root := realms.Join(project, realms.RootRealm)
		if realm == root {
			logging.Warningf(ctx, "Checking %q in a non-existing root realm %q: denying", perm, realm)
			return false, nil
		}
		if !db.realms.HasRealm(root) {
			logging.Warningf(ctx, "Checking %q in a non-existing realm %q that doesn't have a root realm (no such project?): denying", perm, realm)
			return false, nil
		}
		// Don't log @legacy => @root fallbacks, they are semi-expected.
		if name != realms.LegacyRealm {
			logging.Warningf(ctx, "Checking %q in a non-existing realm %q: falling back to the root realm %q", perm, realm, root)
		}
		realm = root
	}

	// Grab the list of bindings for this permission and check if any applies to
	// the `id` based on its group memberships.
	q := db.groups.MembershipsQueryCache(id)
	return db.realms.Bindings(realm, permIdx).Check(ctx, &q, attrs), nil
}

// QueryRealms returns a list of realms where the identity has the given
// permission.
func (db *SnapshotDB) QueryRealms(ctx context.Context, id identity.Identity, perm realms.Permission, project string, attrs realms.Attrs) (out []string, err error) {
	otelAttrs := append(make([]attribute.KeyValue, 0, 2+len(attrs)),
		attribute.String("cr.dev.permission", perm.Name()),
		attribute.String("cr.dev.project", project),
	)
	for k, v := range attrs {
		otelAttrs = append(otelAttrs, attribute.String("cr.dev.attr."+k, v))
	}
	ctx, span := tracing.Start(ctx, "go.chromium.org/luci/server/auth/authdb.QueryRealms",
		otelAttrs...,
	)
	// `out` list can be huge. Just report the number of realms.
	defer func() { tracing.End(span, err, attribute.Int("cr.dev.outcome", len(out))) }()

	if project != "" {
		if err := realms.ValidateProjectName(project); err != nil {
			return nil, err
		}
	}

	// This may happen if the AuthDB proto has no Realms yet.
	if db.realms == nil {
		return nil, errors.Reason("Realms API is not available").Err()
	}

	permIdx, ok := db.realms.PermissionIndex(perm)
	if !ok {
		logging.Warningf(ctx, "Querying realms with permission %q not present in the AuthDB", perm)
		return nil, nil
	}

	// Get the map project => all bindings for the given permission there. This
	// returns `ok == false` if the permission was not flagged with
	// UsedInQueryRealms.
	permBindings, ok := db.realms.QueryBindings(permIdx)
	if !ok {
		return nil, errors.Reason("permission %s cannot be used in QueryRealms: it was not flagged with UsedInQueryRealms flag", perm).Err()
	}

	// For each potentially matching list of bindings, check if it really matches.
	q := db.groups.MembershipsQueryCache(id)
	visit := func(bindings []realmset.RealmBindings) {
		for _, realmBindings := range bindings {
			if realmBindings.Bindings.Check(ctx, &q, attrs) {
				out = append(out, realmBindings.Realm)
			}
		}
	}
	if project != "" {
		visit(permBindings[project])
	} else {
		for _, bindings := range permBindings {
			visit(bindings)
		}
	}

	return out, nil
}

// FilterKnownGroups filters the list of groups keeping only ones that exist.
//
// May return errors if underlying datastore has issues. If all groups are
// unknown, returns an empty list and no error.
func (db *SnapshotDB) FilterKnownGroups(ctx context.Context, groups []string) (known []string, err error) {
	_, span := tracing.Start(ctx, "go.chromium.org/luci/server/auth/authdb.FilterKnownGroups",
		attribute.Int("cr.dev.groups", len(groups)),
	)
	defer func() { tracing.End(span, err, attribute.Int("cr.dev.outcome", len(known))) }()

	if db.groups == nil {
		return nil, nil
	}

	known = make([]string, 0, len(groups))
	for _, gr := range groups {
		if _, ok := db.groups.GroupIndex(gr); ok {
			known = append(known, gr)
		}
	}
	return known, nil
}

// GetCertificates returns a bundle with certificates of a trusted signer.
//
// Currently only the Token Server is a trusted signer.
func (db *SnapshotDB) GetCertificates(ctx context.Context, signerID identity.Identity) (*signing.PublicCertificates, error) {
	if db.tokenServiceURL == "" {
		logging.Warningf(
			ctx, "Delegation is not supported, the token server URL is not set by %s",
			db.AuthServiceURL)
		return nil, nil
	}
	switch tokenServerID, certs, err := db.tokenServiceCerts.GetCerts(ctx); {
	case err != nil:
		return nil, err
	case signerID != tokenServerID:
		return nil, nil // signerID is not trusted since it's not a token server
	default:
		return certs, nil
	}
}

// GetAllowlistForIdentity returns name of the IP allowlist to use to check
// IP of requests from the given `ident`.
//
// It's used to restrict access for certain account to certain IP subnets.
//
// Returns ("", nil) if `ident` is not IP restricted.
func (db *SnapshotDB) GetAllowlistForIdentity(ctx context.Context, ident identity.Identity) (string, error) {
	return db.allowlistedIPs.GetAllowlistForIdentity(ident), nil
}

// IsAllowedIP returns true if IP address belongs to given named IP allowlist.
func (db *SnapshotDB) IsAllowedIP(ctx context.Context, ip net.IP, allowlist string) (bool, error) {
	return db.allowlistedIPs.IsAllowedIP(ip, allowlist), nil
}

// GetAuthServiceURL returns root URL ("https://<host>") of the auth service
// the snapshot was fetched from.
//
// This is needed to implement authdb.DB interface.
func (db *SnapshotDB) GetAuthServiceURL(ctx context.Context) (string, error) {
	if db.AuthServiceURL == "" {
		return "", errors.Reason("not using Auth Service").Err()
	}
	return db.AuthServiceURL, nil
}

// GetTokenServiceURL returns root URL ("https://<host>") of the token server.
//
// This is needed to implement authdb.DB interface.
func (db *SnapshotDB) GetTokenServiceURL(ctx context.Context) (string, error) {
	return db.tokenServiceURL, nil
}

// GetRealmData returns data attached to a realm.
func (db *SnapshotDB) GetRealmData(ctx context.Context, realm string) (*protocol.RealmData, error) {
	// This may happen if the AuthDB proto has no Realms yet.
	if db.realms == nil {
		return nil, errors.Reason("Realms API is not available").Err()
	}

	// Verify such realm is defined in the DB or fallback to its @root.
	if !db.realms.HasRealm(realm) {
		if err := realms.ValidateRealmName(realm, realms.GlobalScope); err != nil {
			return nil, err
		}
		project, _ := realms.Split(realm)
		root := realms.Join(project, realms.RootRealm)
		if realm == root || !db.realms.HasRealm(root) {
			return nil, nil // no such project or it doesn't have realms.cfg
		}
		realm = root
	}

	data := db.realms.Data(realm)
	if data == nil {
		data = &protocol.RealmData{}
	}
	return data, nil
}
