보안 및 접근 제어
security 모듈은 인증 액터, 권한 부여 스코프, 정책, 토큰 스토어를 제공합니다. 이 페이지는 부분적인 권한 부여 레시피를 포함한 API 참조입니다. 레지스트리 ID, 액터, 요청 메타데이터, 토큰 값, user 및 doc 같은 애플리케이션 객체, show_admin_features 같은 콜백은 주변 애플리케이션에서 제공되며, 예제만으로 완전한 인증 배포가 구성되지는 않습니다.
Wippy는 기본적으로 엄격한 보안 모드에서 실행됩니다. 실행 엔트리는 security를 활성화하고 액터와 스코프를 가지며 호출하는 정확한 작업을 허가해야 합니다. 특히 생성 및 스코프 변경에는 security.actor.create 또는 security.scope.create, 레지스트리 조회에는 security.policy.get 또는 security.policy_group.get, 토큰 작업에는 security.token_store.get과 작업별 토큰 권한이 필요합니다. new_actor, new_scope, scope:with, scope:without, 권한이 거부된 token_store 획득은 구조화된 error를 반환하지 않고 Lua 오류를 발생시킵니다. 거부 후 복구하려 하지 말고 엔트리의 보안 컨텍스트에서 이러한 사전 요구 사항을 허가하세요. 구성 방법은 보안 모델을 참조하세요.
로딩
local security = require("security")
actor
실행 컨텍스트에서 현재 보안 액터를 반환합니다.
local actor = security.actor()
if actor then
local id = actor:id()
local meta = actor:meta()
-- Use only the fields required for authorization or application logic.
local role = meta.role
end
액터 메타데이터에는 식별자나 개인 데이터가 포함될 수 있습니다. 전체 메타데이터 테이블을 기록하거나 비밀 값을 저장하지 마세요.
반환: Actor|nil
scope
실행 컨텍스트에서 현재 보안 스코프를 반환합니다.
local scope = security.scope()
if scope then
local policies = scope:policies()
for _, policy in ipairs(policies) do
print("Active policy:", policy:id())
end
end
반환: Scope|nil
can
현재 컨텍스트가 리소스에 대한 액션을 허용하는지 확인합니다.
-- Check read permission
if not security.can("read", "user:" .. user_id) then
return nil, errors.new("Cannot read user data"):kind(errors.PERMISSION_DENIED)
end
-- Check write permission
if not security.can("write", "order:" .. order_id) then
return nil, errors.new("Cannot modify order"):kind(errors.PERMISSION_DENIED)
end
-- Check with metadata
local allowed = security.can("delete", "document:" .. doc_id, {
owner_id = doc.owner_id,
department = doc.department
})
| 파라미터 | 타입 | 설명 |
|---|---|---|
action |
string | 확인할 액션 |
resource |
string | 리소스 식별자 |
meta |
table | 추가 메타데이터 (선택적) |
반환: boolean
new_actor
ID와 메타데이터로 새 액터를 생성합니다.
-- Create user actor
local actor = security.new_actor("user:" .. user.id, {
role = user.role,
department = user.department,
email = user.email
})
-- Create service actor
local service_actor = security.new_actor("service:payment-processor", {
type = "service",
version = "1.0.0"
})
| 파라미터 | 타입 | 설명 |
|---|---|---|
id |
string | 고유 액터 식별자 |
meta |
table | 메타데이터 키-값 쌍 |
반환: Actor
new_scope
새 커스텀 스코프를 생성합니다.
-- Empty scope
local scope = security.new_scope()
-- Scope with policies
local read_policy, read_err = security.policy("app:read-only")
if read_err then
return nil, read_err
end
local scope = security.new_scope({read_policy})
-- Build scope incrementally
local scope = security.new_scope()
local policy1, policy1_err = security.policy("app:read")
if policy1_err then
return nil, policy1_err
end
local policy2, policy2_err = security.policy("app:write")
if policy2_err then
return nil, policy2_err
end
scope = scope:with(policy1):with(policy2)
위의 각 대안은 서로 독립적인 생성 패턴입니다. 컨텍스트가 없거나 권한이 거부되면 new_scope와 scope:with는 오류를 발생시키며, 이러한 검사에서 nil, error를 반환하지 않습니다.
반환: Scope
policy
레지스트리에서 정책을 가져옵니다.
local policy, err = security.policy("app:admin-access")
if err then
return nil, err
end
-- Evaluate policy
local result = policy:evaluate(actor, "delete", "user:123")
if result == "allow" then
-- permitted
elseif result == "deny" then
-- forbidden
else
-- undefined, check other policies
end
| 파라미터 | 타입 | 설명 |
|---|---|---|
id |
string | 정책 ID "namespace:name" |
반환: Policy, error
named_scope
미리 정의된 정책 그룹을 가져옵니다.
-- Get admin scope
local admin_scope, err = security.named_scope("app:admin")
if err then
return nil, err
end
-- Use for elevated operations
local result = admin_scope:evaluate(actor, "delete", "user:123")
스코프를 로드해도 현재 실행 컨텍스트의 권한이 상승하지는 않습니다. 명시적 평가나 스코프를 받는 API에 사용할 값을 생성할 뿐이며, 호출자는 보호된 작업을 수행할 권한을 여전히 갖추어야 합니다.
| 파라미터 | 타입 | 설명 |
|---|---|---|
id |
string | 정책 그룹 ID |
반환: Scope, error
token_store
인증 토큰 관리를 위한 토큰 스토어를 획득합니다.
local store, err = security.token_store("app:tokens")
if err then
return nil, err
end
-- Use store...
return store:close()
획득한 토큰 스토어는 close()를 호출할 때까지 호출자가 소유합니다. 검사된 모든 성공 및 오류 경로에서 마지막 작업 후 닫으세요. 반복해서 닫아도 안전합니다. 획득 중 권한 거부는 Lua 오류를 발생시키지만, 조회 및 리소스 실패는 nil, error를 반환합니다.
| 파라미터 | 타입 | 설명 |
|---|---|---|
id |
string | 토큰 스토어 ID "namespace:name" |
반환: TokenStore, error
Actor 메서드
| 메서드 | 반환 | 설명 |
|---|---|---|
actor:id() |
string | 액터 식별자 |
actor:meta() |
table | 액터 메타데이터 |
Scope 메서드
with / without
스코프에서 정책을 추가하거나 제거합니다.
local scope = security.new_scope()
-- Add policy
local write_policy, err = security.policy("app:write")
if err then
return nil, err
end
scope = scope:with(write_policy)
-- Remove policy
scope = scope:without("app:read-only")
with와 without은 새로운 불변 스코프 값을 반환하며, with 또는 without 리소스에 security.scope.create가 허용되지 않으면 오류를 발생시킵니다.
evaluate
스코프 내 모든 정책을 평가합니다.
local result = scope:evaluate(actor, "read", "document:123")
-- "allow", "deny", or "undefined"
if result ~= "allow" then
return nil, errors.new("Access denied"):kind(errors.PERMISSION_DENIED)
end
contains
스코프에 정책이 포함되어 있는지 확인합니다.
if scope:contains("app:admin") then
show_admin_features()
end
policies
스코프 내 모든 정책을 반환합니다.
local policies = scope:policies()
for _, policy in ipairs(policies) do
print(policy:id())
end
반환: Policy[]
Policy 메서드
| 메서드 | 반환 | 설명 |
|---|---|---|
policy:id() |
string | 정책 식별자 |
policy:evaluate(actor, action, resource, meta?) |
string | "allow", "deny", 또는 "undefined" |
TokenStore 메서드
create
인증 토큰을 생성합니다.
local actor = security.new_actor("user:123", {role = "user"})
local scope, scope_err = security.named_scope("app:default")
if scope_err then
return nil, scope_err
end
local store, store_err = security.token_store("app:tokens")
if store_err then
return nil, store_err
end
local token, err = store:create(actor, scope, {
expiration = "24h", -- or milliseconds
meta = {
login_ip = request_ip,
user_agent = user_agent
}
})
store:close()
if err then
return nil, err
end
return token
request_ip와 user_agent는 애플리케이션이 제공하는 요청 값입니다. 보안 결정에 필요한 메타데이터만 저장하고 보존 한도를 적용하며, 반환된 베어러 토큰을 의도한 자격 증명 저장소 밖에 기록하거나 보관하지 마세요.
| 파라미터 | 타입 | 설명 |
|---|---|---|
actor |
Actor | 토큰의 액터 |
scope |
Scope | 권한 스코프 |
options.expiration |
string/number | 기간 문자열 또는 ms |
options.meta |
table | 토큰 메타데이터 |
반환: string, error
validate
토큰을 검증하고 actor/scope를 가져옵니다.
local actor, scope, err = store:validate(token)
store:close()
if err then
return nil, errors.new("Invalid token"):kind(errors.PERMISSION_DENIED)
end
여기와 아래에서 store는 소유 중인 활성 핸들이고 token은 호출자가 제공하는 신뢰할 수 없는 베어러 자격 증명입니다. 검증 또는 폐기 오류가 발생하더라도 토큰을 기록하지 마세요.
반환: Actor, Scope, error
revoke
토큰을 무효화합니다.
local ok, err = store:revoke(token)
store:close()
if err then
return nil, err
end
반환: boolean, error
close
토큰 스토어 리소스를 해제합니다.
store:close()
반환: boolean
권한
보안 작업은 보안 정책 평가 대상입니다.
보안 액션
| 액션 | 리소스 | 설명 |
|---|---|---|
security.policy.get |
정책 ID | 정책 정의 접근 |
security.policy_group.get |
그룹 ID | 명명된 스코프 접근 |
security.scope.create |
custom, with, without |
커스텀 스코프 생성(new_scope) 및 정책 추가/제거(scope:with, scope:without) |
security.actor.create |
액터 ID | 액터 생성 |
security.token_store.get |
스토어 ID | 토큰 스토어 접근 |
security.token.validate |
스토어 ID | 토큰 검증 |
security.token.create |
스토어 ID | 토큰 생성 |
security.token.revoke |
스토어 ID | 토큰 폐기 |
정책 설정은 보안 모델을 참조하세요.
에러
| 조건 | 종류 | 재시도 가능 |
|---|---|---|
| 컨텍스트 없음 | errors.INTERNAL |
아니오 |
| 빈 토큰 스토어 ID | errors.INVALID |
아니오 |
권한 거부됨 (policy, named_scope, 토큰 create/validate/revoke) |
errors.INVALID |
아니오 |
권한 거부됨 (new_scope, new_actor, token_store, scope:with/without) |
Lua 에러로 발생 | 아니오 |
| 정책을 찾을 수 없음 | errors.INTERNAL |
아니오 |
| 토큰 스토어를 찾을 수 없음 | errors.INTERNAL |
아니오 |
| 토큰 스토어 닫힘 | errors.INTERNAL |
아니오 |
| 잘못된 만료 형식 | errors.INVALID |
아니오 |
| 토큰 검증 실패 | errors.INTERNAL |
아니오 |
local store, err = security.token_store("app:tokens")
if err then
if errors.is(err, errors.INVALID) then
print("Invalid request:", err:message())
end
return nil, err
end
store:close()
에러 처리는 에러 처리를 참조하세요.