Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(125)

Unified Diff: go/src/infra/libs/auth/service.go

Issue 1153883002: go: infra/libs/* now live in luci-go. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: move the rest too Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « go/src/infra/libs/auth/internal/user.go ('k') | go/src/infra/libs/auth/service_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: go/src/infra/libs/auth/service.go
diff --git a/go/src/infra/libs/auth/service.go b/go/src/infra/libs/auth/service.go
deleted file mode 100644
index 401be28baa4cff6b9bfe1631f5761afee938eb73..0000000000000000000000000000000000000000
--- a/go/src/infra/libs/auth/service.go
+++ /dev/null
@@ -1,251 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package auth
-
-import (
- "encoding/json"
- "errors"
- "fmt"
- "io/ioutil"
- "net/http"
- "strings"
- "time"
-
- "infra/libs/logging"
-)
-
-// ServiceURL is URL of a service to talk to by default.
-const ServiceURL string = "https://chrome-infra-auth.appspot.com"
-
-// IdentityKind is enum like type with possible kinds of identities.
-type IdentityKind string
-
-const (
- // IdentityKindUnknown is used when server return identity kind not recognized
- // by the client.
- IdentityKindUnknown IdentityKind = ""
- // IdentityKindAnonymous is used to represent anonymous callers.
- IdentityKindAnonymous IdentityKind = "anonymous"
- // IdentityKindBot is used to represent bots. Identity name is bot's IP.
- IdentityKindBot IdentityKind = "bot"
- // IdentityKindService is used to represent AppEngine apps when they use
- // X-Appengine-Inbound-AppId header to authenticate. Identity name is app ID.
- IdentityKindService IdentityKind = "service"
- // IdentityKindUser is used to represent end users or OAuth service accounts.
- // Identity name is an associated email (user email or service account email).
- IdentityKindUser IdentityKind = "user"
-)
-
-var (
- // ErrAccessDenied is returned by GroupsService methods if caller doesn't have
- // enough permissions to execute an action. Corresponds to 403 HTTP status.
- ErrAccessDenied = errors.New("Access denied (HTTP 403)")
-
- // ErrNoSuchItem is returned by GroupsService methods if requested item
- // (e.g. a group) doesn't exist. Corresponds to 404 HTTP status.
- ErrNoSuchItem = errors.New("No such item (HTTP 404)")
-)
-
-// Identity represents some caller that can make requests. It generalizes
-// accounts of real people, bot accounts and service-to-service accounts.
-type Identity struct {
- // Kind describes what sort of identity this struct represents.
- Kind IdentityKind
- // Name defines concrete instance of identity, its meaning depends on kind.
- Name string
-}
-
-// Group is a named list of identities, included subgroups and glob-like
-// patterns (e.g. "user:*@example.com).
-type Group struct {
- // Name is a name of the group.
- Name string
- // Description is a human readable description of the group.
- Description string
- // Members is a list of identities included in the group explicitly.
- Members []Identity
- // Globs is a list of glob-like patterns for identities.
- Globs []string
- // Nested is a list of group names included into this group.
- Nested []string
-}
-
-// String returns human readable representation of Identity.
-func (i Identity) String() string {
- switch i.Kind {
- case IdentityKindUnknown:
- return "unknown"
- case IdentityKindAnonymous:
- return "anonymous"
- case IdentityKindUser:
- return i.Name
- default:
- return fmt.Sprintf("%s:%s", i.Kind, i.Name)
- }
-}
-
-// GroupsService knows how to talk to Groups API backend. Server side code
-// is in https://github.com/luci/luci-py repository.
-type GroupsService struct {
- client *http.Client
- serviceURL string
- logger logging.Logger
-}
-
-// NewGroupsService constructs new instance of GroupsService that talks to given
-// service URL via given http.Client. If url is empty string, the default
-// backend will be used. If httpClient is nil, http.DefaultClient will be used.
-func NewGroupsService(url string, client *http.Client, logger logging.Logger) *GroupsService {
- if url == "" {
- url = ServiceURL
- }
- if client == nil {
- client = http.DefaultClient
- }
- if logger == nil {
- logger = logging.Null()
- }
- return &GroupsService{
- client: client,
- serviceURL: url,
- logger: logger,
- }
-}
-
-// ServiceURL returns a string with root URL of a Groups backend.
-func (s *GroupsService) ServiceURL() string {
- return s.serviceURL
-}
-
-// FetchCallerIdentity returns caller's own Identity as seen by the server.
-func (s *GroupsService) FetchCallerIdentity() (Identity, error) {
- var response struct {
- Identity string `json:"identity"`
- }
- err := s.doGet("/auth/api/v1/accounts/self", &response)
- if err != nil {
- return Identity{}, err
- }
- return parseIdentity(response.Identity)
-}
-
-// FetchGroup returns a group definition. It does not fetch nested groups.
-// Returns ErrNoSuchItem error if no such group.
-func (s *GroupsService) FetchGroup(name string) (Group, error) {
- var response struct {
- Group struct {
- Name string `json:"name"`
- Description string `json:"description"`
- Members []string `json:"members"`
- Globs []string `json:"globs"`
- Nested []string `json:"nested"`
- } `json:"group"`
- }
- err := s.doGet("/auth/api/v1/groups/"+name, &response)
- if err != nil {
- return Group{}, err
- }
- if response.Group.Name != name {
- return Group{}, fmt.Errorf(
- "Unexpected group name in server response: '%s', expecting '%s'",
- response.Group.Name, name)
- }
- g := Group{
- Name: response.Group.Name,
- Description: response.Group.Description,
- Members: make([]Identity, 0, len(response.Group.Members)),
- Globs: response.Group.Globs,
- Nested: response.Group.Nested,
- }
- for _, str := range response.Group.Members {
- ident, err := parseIdentity(str)
- if err != nil {
- s.logger.Warningf("auth: failed to parse an identity in a group, ignoring it - %s", err)
- } else {
- g.Members = append(g.Members, ident)
- }
- }
- return g, nil
-}
-
-// doGet sends GET HTTP requests and decodes JSON into response. It retries
-// multiple times on transient errors.
-func (s *GroupsService) doGet(path string, response interface{}) error {
- if len(path) == 0 || path[0] != '/' {
- return fmt.Errorf("Path should start with '/': %s", path)
- }
- url := s.serviceURL + path
- for attempt := 0; attempt < 5; attempt++ {
- if attempt != 0 {
- s.logger.Warningf("auth: retrying request to %s", url)
- sleep(2 * time.Second)
- }
- req, err := http.NewRequest("GET", url, nil)
- if err != nil {
- return err
- }
- resp, err := doRequest(s.client, req)
- if err != nil {
- return err
- }
- // Success?
- if resp.StatusCode < 300 {
- defer resp.Body.Close()
- return json.NewDecoder(resp.Body).Decode(response)
- }
- // Fatal error?
- if resp.StatusCode >= 300 && resp.StatusCode < 500 {
- defer resp.Body.Close()
- switch resp.StatusCode {
- case 403:
- return ErrAccessDenied
- case 404:
- return ErrNoSuchItem
- default:
- body, _ := ioutil.ReadAll(resp.Body)
- return fmt.Errorf("Unexpected reply (HTTP %d):\n%s", resp.StatusCode, string(body))
- }
- }
- // Retry.
- resp.Body.Close()
- }
- return fmt.Errorf("Request to %s failed after 5 attempts", url)
-}
-
-// parseIdentity takes a string of form "<kind>:<name>" and returns Identity
-// struct.
-func parseIdentity(str string) (Identity, error) {
- chunks := strings.Split(str, ":")
- if len(chunks) != 2 {
- return Identity{}, fmt.Errorf("Invalid identity string: '%s'", str)
- }
- kind := IdentityKind(chunks[0])
- name := chunks[1]
- switch kind {
- case IdentityKindAnonymous:
- if name != "anonymous" {
- return Identity{}, fmt.Errorf("Invalid anonymous identity: '%s'", str)
- }
- return Identity{
- Kind: IdentityKindAnonymous,
- Name: "anonymous",
- }, nil
- case IdentityKindBot, IdentityKindService, IdentityKindUser:
- return Identity{
- Kind: kind,
- Name: name,
- }, nil
- default:
- return Identity{}, fmt.Errorf("Unrecognized identity kind: '%s'", str)
- }
-}
-
-// sleep is mocked in tests.
-var sleep = time.Sleep
-
-// doRequest is mocked in tests.
-var doRequest = func(c *http.Client, req *http.Request) (*http.Response, error) {
- return c.Do(req)
-}
« no previous file with comments | « go/src/infra/libs/auth/internal/user.go ('k') | go/src/infra/libs/auth/service_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698