일반론적으로
인증은 특정 API 로 요청이 들어왔을때, 이 요청을 누가 했는지 알아내는 과정을 말하며
인가는 인증을 통해 알아낸 사람이 특정 리소스에 접근이 가능하게 할 지 알아내는 과정을 말한다.
말은 쉽지만, 사실 대부분 겉보기에는 인증과 인가가 잘 구분되어있는것처럼 보이지만, 코드를 뜯어보면 인가를 해야할곳에서 인증을 하고, 인증을 해야할곳에서 인가를 하는경우가 종종 있다.
아니 정확히 말하면 종종 정도가 아니라 수십개의 오픈소스, Closed 소스를 뜯어보면서 각자 이러저러한 이유와 변명이 있겠지만 인증과 인가를 깔끔하면서도 제대로 명확하게 구분해서 짠 코드를 본것은 Kubernetes 가 유일했다. (여기서 뜯어본 프로젝트란 Spring, Openstack, Jenkins 를 포함한다.)
간단하게 맛보기로 소개해보면 Kubernetes 에서 모든 인증은
kubernetes/interfaces.go at v1.21.11 · kubernetes/kubernetes
// Request attempts to extract authentication information from a request and
// returns a Response or an error if the request could not be checked.
type Request interface {
AuthenticateRequest(req *http.Request) (*Response, bool, error)
}
위 인터페이스의 구현체로, HTTP 관점에서 Header, TLS Connection 등에 포함된 정보만 보고 이 요청을 보낸 유저가 누구인지에 대한 정보를 알아내는데만 초점이 맞춰져 있으며 최종적으로는 다음 인터페이스를 반환하며 유저의 이름과 소속그룹에대해 string 정보를 알아내는 역할만 수행한다.
// Info describes a user that has been authenticated to the system.
type user.Info interface {
// GetName returns the name that uniquely identifies this user among all
// other active users.
**GetName() string**
// GetGroups returns the names of the groups the user is a member of
**GetGroups() []string**
// Not that importants
GetUID() string
GetExtra() map[string][]string // 이건 좀 특수한케이스에서 사용
}
인가 단계에서는
Verb 로 어떤 GVK, NamespaceName 로 요청을 걸 고 있는지에 대한 정보두가지를 보고
kubernetes/interfaces.go at v1.21.11 · kubernetes/kubernetes
// Authorizer makes an authorization decision based on information gained by making
// zero or more calls to methods of the Attributes interface. It returns nil when an action is
// authorized, otherwise it returns an error.
type Authorizer interface {
Authorize(ctx context.Context, a Attributes) (authorized Decision, reason string, err error)
}
위 인터페이스를 수행한 결과에 대해서 DecisionAllow, DecisionDeny, or DecisionNoOpinion 세가지 결론을 내는 역할만 수행한다.