// Code generated by protoc-gen-go. DO NOT EDIT.
// source: auth/acl.proto

package auth

import (
	fmt "fmt"
	proto "github.com/golang/protobuf/proto"
	math "math"
)

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package

// Group defines a group of users that shares the same service account.
// Different groups may share a service account.
type Group struct {
	Id          string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
	Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
	// if audience is not empty, group member should have this audience
	// in the token.
	Audience string `protobuf:"bytes,3,opt,name=audience,proto3" json:"audience,omitempty"`
	// matches mail in the token.
	Emails []string `protobuf:"bytes,4,rep,name=emails,proto3" json:"emails,omitempty"`
	// matches domain part of email in the token.
	Domains []string `protobuf:"bytes,5,rep,name=domains,proto3" json:"domains,omitempty"`
	// use this service account for this group.
	// it is used to read json in service-accounts volume.
	// If service_account is "default", use server's default service account.
	// If service_account is empty, pass EUC as is.
	ServiceAccount string `protobuf:"bytes,6,opt,name=service_account,json=serviceAccount,proto3" json:"service_account,omitempty"`
	// If reject is true, deny access from this group.
	// Used for blacklisting.
	Reject               bool     `protobuf:"varint,7,opt,name=reject,proto3" json:"reject,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *Group) Reset()         { *m = Group{} }
func (m *Group) String() string { return proto.CompactTextString(m) }
func (*Group) ProtoMessage()    {}
func (*Group) Descriptor() ([]byte, []int) {
	return fileDescriptor_91b80568fa5a4647, []int{0}
}

func (m *Group) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_Group.Unmarshal(m, b)
}
func (m *Group) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_Group.Marshal(b, m, deterministic)
}
func (m *Group) XXX_Merge(src proto.Message) {
	xxx_messageInfo_Group.Merge(m, src)
}
func (m *Group) XXX_Size() int {
	return xxx_messageInfo_Group.Size(m)
}
func (m *Group) XXX_DiscardUnknown() {
	xxx_messageInfo_Group.DiscardUnknown(m)
}

var xxx_messageInfo_Group proto.InternalMessageInfo

func (m *Group) GetId() string {
	if m != nil {
		return m.Id
	}
	return ""
}

func (m *Group) GetDescription() string {
	if m != nil {
		return m.Description
	}
	return ""
}

func (m *Group) GetAudience() string {
	if m != nil {
		return m.Audience
	}
	return ""
}

func (m *Group) GetEmails() []string {
	if m != nil {
		return m.Emails
	}
	return nil
}

func (m *Group) GetDomains() []string {
	if m != nil {
		return m.Domains
	}
	return nil
}

func (m *Group) GetServiceAccount() string {
	if m != nil {
		return m.ServiceAccount
	}
	return ""
}

func (m *Group) GetReject() bool {
	if m != nil {
		return m.Reject
	}
	return false
}

type ACL struct {
	// First matched group will be used.
	Groups               []*Group `protobuf:"bytes,1,rep,name=groups,proto3" json:"groups,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *ACL) Reset()         { *m = ACL{} }
func (m *ACL) String() string { return proto.CompactTextString(m) }
func (*ACL) ProtoMessage()    {}
func (*ACL) Descriptor() ([]byte, []int) {
	return fileDescriptor_91b80568fa5a4647, []int{1}
}

func (m *ACL) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_ACL.Unmarshal(m, b)
}
func (m *ACL) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_ACL.Marshal(b, m, deterministic)
}
func (m *ACL) XXX_Merge(src proto.Message) {
	xxx_messageInfo_ACL.Merge(m, src)
}
func (m *ACL) XXX_Size() int {
	return xxx_messageInfo_ACL.Size(m)
}
func (m *ACL) XXX_DiscardUnknown() {
	xxx_messageInfo_ACL.DiscardUnknown(m)
}

var xxx_messageInfo_ACL proto.InternalMessageInfo

func (m *ACL) GetGroups() []*Group {
	if m != nil {
		return m.Groups
	}
	return nil
}

func init() {
	proto.RegisterType((*Group)(nil), "auth.Group")
	proto.RegisterType((*ACL)(nil), "auth.ACL")
}

func init() { proto.RegisterFile("auth/acl.proto", fileDescriptor_91b80568fa5a4647) }

var fileDescriptor_91b80568fa5a4647 = []byte{
	// 220 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x90, 0xc1, 0x4a, 0xc4, 0x30,
	0x10, 0x86, 0x49, 0xbb, 0xdb, 0xdd, 0x9d, 0x42, 0x85, 0x39, 0xc8, 0xe0, 0x29, 0xac, 0x07, 0x8b,
	0x87, 0x0a, 0xfa, 0x04, 0x8b, 0x07, 0x2f, 0x9e, 0xfa, 0x02, 0x12, 0x93, 0x41, 0x47, 0xb6, 0x4d,
	0x49, 0x52, 0x9f, 0xd1, 0xc7, 0x92, 0xc6, 0x2a, 0x1e, 0xbf, 0xff, 0x83, 0x81, 0x6f, 0xa0, 0x31,
	0x73, 0x7a, 0xbf, 0x33, 0xf6, 0xdc, 0x4d, 0xc1, 0x27, 0x8f, 0x9b, 0x85, 0x8f, 0x5f, 0x0a, 0xb6,
	0x4f, 0xc1, 0xcf, 0x13, 0x36, 0x50, 0x88, 0x23, 0xa5, 0x55, 0x7b, 0xe8, 0x0b, 0x71, 0xa8, 0xa1,
	0x76, 0x1c, 0x6d, 0x90, 0x29, 0x89, 0x1f, 0xa9, 0xc8, 0xe2, 0xff, 0x84, 0x57, 0xb0, 0x37, 0xb3,
	0x13, 0x1e, 0x2d, 0x53, 0x99, 0xf5, 0x1f, 0xe3, 0x25, 0x54, 0x3c, 0x18, 0x39, 0x47, 0xda, 0xe8,
	0xb2, 0x3d, 0xf4, 0x2b, 0x21, 0xc1, 0xce, 0xf9, 0xc1, 0xc8, 0x18, 0x69, 0x9b, 0xc5, 0x2f, 0xe2,
	0x0d, 0x5c, 0x44, 0x0e, 0x9f, 0x62, 0xf9, 0xc5, 0x58, 0xeb, 0xe7, 0x31, 0x51, 0x95, 0x8f, 0x36,
	0xeb, 0x7c, 0xfa, 0x59, 0x97, 0xd3, 0x81, 0x3f, 0xd8, 0x26, 0xda, 0x69, 0xd5, 0xee, 0xfb, 0x95,
	0x8e, 0xb7, 0x50, 0x9e, 0x1e, 0x9f, 0xf1, 0x1a, 0xaa, 0xb7, 0x25, 0x28, 0x92, 0xd2, 0x65, 0x5b,
	0xdf, 0xd7, 0xdd, 0x12, 0xda, 0xe5, 0xc8, 0x7e, 0x55, 0xaf, 0x55, 0xfe, 0xc1, 0xc3, 0x77, 0x00,
	0x00, 0x00, 0xff, 0xff, 0x10, 0x70, 0xfe, 0xad, 0x15, 0x01, 0x00, 0x00,
}
