## 들어가며
오픈소스 위키 플랫폼인 Wiki.js를 팀 문서화 도구로 사용하다 보면, 신규 계정 생성이나 권한 관리를 자동화하고 싶은 순간이 찾아옵니다. 특히 봇 계정이나 서비스 계정을 생성할 때 매번 수동으로 웹 인터페이스에 접속하는 것은 비효율적이죠.
이번 글에서는 Wiki.js API를 활용한 계정 생성 자동화 과정에서 겪은 권한 문제와 해결 방법을 공유합니다.
## 문제 상황: API 호출이 Forbidden?
### 초기 시도
Wiki.js는 GraphQL API를 제공하므로, 다음과 같이 사용자 생성 mutation을 호출했습니다:
```bash
curl -X POST http://your-wiki-server:3000/graphql \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation { users { create(name: \"forge\", email: \"forge@example.com\", passwordRaw: \"secure_password\", providerKey: \"local\") { responseResult { succeeded } } } }"
}'
```
### 예상치 못한 결과
```json
{
"errors": [
{
"message": "Forbidden",
"locations": [{"line": 1, "column": 12}],
"path": ["users", "create"]
}
]
}
```
API 토큰이 유효함에도 불구하고 `Forbidden` 에러가 발생했습니다. 원인은 **API 토큰의 권한 범위(scope) 설정**에 있었습니다.
## 원인 분석: Wiki.js API 토큰 권한 구조
Wiki.js의 API 토큰은 생성 시 권한 범위를 지정할 수 있습니다:
- `read:pages` - 페이지 읽기
- `write:pages` - 페이지 작성/수정
- `read:users` - 사용자 정보 조회
- `write:users` - 사용자 생성/수정/삭제
- `read:groups` - 그룹 정보 조회
- `write:groups` - 그룹 관리
일반적으로 문서 작성용으로 생성된 토큰은 `write:pages` 권한만 가지고 있어, 사용자 관리 API 호출이 거부됩니다.
## 해결 방법
### 방법 1: 수동 계정 생성 (즉시 해결)
권한 업그레이드가 어려운 상황이라면, 관리자 웹 인터페이스를 활용합니다:
1. `http://your-wiki-server:3000/a/users` 접속
2. **New User** 버튼 클릭
3. 필요한 정보 입력:
- Email: 계정 이메일
- Name: 표시 이름
- Provider: Local (내부 인증)
- Role: Editor, Administrator 등 선택
4. 임시 비밀번호 설정 후 생성
### 방법 2: API 토큰 권한 업그레이드 (자동화 구축)
장기적인 자동화를 위해서는 토큰 권한을 조정해야 합니다:
#### 단계 1: 관리자 계정으로 로그인
#### 단계 2: API Access 페이지 이동
- Administration → API → API Access
#### 단계 3: 기존 토큰 편집 또는 신규 생성
- 토큰 이름: `automation_token`
- 만료일: 설정 또는 무제한
- **권한 설정**:
- ✅ `write:users` (사용자 생성/수정)
- ✅ `read:users` (사용자 조회)
- ✅ `write:groups` (필요시 그룹 할당)
#### 단계 4: 토큰 저장 및 안전한 보관
토큰은 생성 시 **한 번만** 표시되므로, 안전한 비밀 관리 도구(Vault, 환경변수 등)에 저장합니다.
### 방법 3: 자동화 스크립트 작성
권한이 부여된 토큰으로 자동화 스크립트를 작성할 수 있습니다:
```javascript
// create-wiki-user.js
const axios = require('axios');
const WIKI_API = 'http://your-wiki-server:3000/graphql';
const API_TOKEN = process.env.WIKI_API_TOKEN;
async function createUser(email, name, role = 'Editor') {
const mutation = `
mutation CreateUser($email: String!, $name: String!, $password: String!, $role: String!) {
users {
create(
email: $email
name: $name
passwordRaw: $password
providerKey: "local"
groups: [$role]
) {
responseResult {
succeeded
errorCode
slug
message
}
user {
id
email
}
}
}
}
`;
const variables = {
email,
name,
password: generateSecurePassword(),
role
};
try {
const response = await axios.post(WIKI_API, {
query: mutation,
variables
}, {
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json'
}
});
if (response.data.errors) {
console.error('GraphQL Errors:', response.data.errors);
return null;
}
return response.data.data.users.create;
} catch (error) {
console.error('API Request Failed:', error.message);
return null;
}
}
function generateSecurePassword() {
return require('crypto').randomBytes(16).toString('hex');
}
// 사용 예시
createUser('newuser@example.com', 'New User', 'Editor')
.then(result => {
if (result && result.responseResult.succeeded) {
console.log('✓ User created:', result.user.email);
} else {
console.log('✗ Failed:', result?.responseResult.message);
}
});
```
## 추가 고려사항
### 1. SSH 접근 제한 환경에서의 대안
컨테이너 환경이나 네트워크 제한이 있는 서버에서는 SSH 접속이 불가능할 수 있습니다. 이 경우:
- **웹 기반 관리**: Admin UI 활용
- **API 기반 자동화**: 네트워크 접근 가능한 위치에서 API 호출
- **CI/CD 통합**: GitLab CI, GitHub Actions 등에서 자동화 스크립트 실행
### 2. 보안 모범 사례
- **최소 권한 원칙**: 필요한 권한만 부여
- **토큰 만료 설정**: 장기 토큰 대신 주기적 갱신
- **환경변수 사용**: 코드에 토큰 하드코딩 금지
- **감사 로그 활성화**: API 호출 기록 모니터링
### 3. 에러 처리
```javascript
if (response.data.errors) {
const errorCode = response.data.errors[0].message;
switch(errorCode) {
case 'Forbidden':
console.error('권한 부족: API 토큰에 write:users 권한 필요');
break;
case 'UserEmailExists':
console.error('이메일이 이미 존재합니다');
break;
default:
console.error('알 수 없는 오류:', errorCode);
}
}
```
## 결론
Wiki.js API를 활용한 계정 생성 자동화는 토큰 권한 설정이 핵심입니다. 초기에는 수동 작업으로 긴급 상황을 해결하되, 장기적으로는 적절한 권한을 가진 API 토큰과 자동화 스크립트를 구축하는 것이 효율적입니다.
**다음 단계로 시도해볼 것들:**
- Wiki.js Webhook 연동으로 계정 생성 이벤트 자동화
- LDAP/SSO 통합으로 중앙 집중식 계정 관리
- GraphQL API 전체 스키마 탐색으로 추가 자동화 기회 발굴
Wiki.js의 강력한 API를 활용하면 문서화 워크플로우를 한층 더 효율적으로 만들 수 있습니다.