Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: サーバー初期設定時に初期パスワードを要求できるように #14626

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1f2012f
feat: サーバー初期設定時専用の初期パスワードを設定できるように
kakkokari-gtyih Sep 25, 2024
e4316d3
無いのに入力された場合もエラーにする
kakkokari-gtyih Sep 25, 2024
21b4b7d
:art:
kakkokari-gtyih Sep 25, 2024
d6dee34
:art:
kakkokari-gtyih Sep 25, 2024
8076f07
cypress-devcontainerにもpassを設定(テストが失敗するため)
kakkokari-gtyih Sep 25, 2024
918f731
Merge branch 'feat-setup-initial-password' of https://github.com/kakk…
kakkokari-gtyih Sep 25, 2024
910a743
[ci skip] :art:
kakkokari-gtyih Sep 25, 2024
4d93fe6
:v:
kakkokari-gtyih Sep 25, 2024
66b2b48
test: please revert this commit before merge
kakkokari-gtyih Sep 25, 2024
7f16f5b
Revert "test: please revert this commit before merge"
kakkokari-gtyih Sep 25, 2024
581d572
Update locales/ja-JP.yml
kakkokari-gtyih Sep 25, 2024
be6111e
build assets
kakkokari-gtyih Sep 25, 2024
a2a74c1
Update Changelog
kakkokari-gtyih Sep 25, 2024
5e85fb6
Merge branch 'develop' into feat-setup-initial-password
kakkokari-gtyih Sep 25, 2024
adcb84f
fix condition
kakkokari-gtyih Sep 25, 2024
67315a5
Merge branch 'feat-setup-initial-password' of https://github.com/kakk…
kakkokari-gtyih Sep 25, 2024
e01d714
fix condition
kakkokari-gtyih Sep 25, 2024
72c02b6
add comment
kakkokari-gtyih Sep 25, 2024
85eb2ef
change error code
kakkokari-gtyih Sep 26, 2024
73235e9
他のエラーコードと合わせる
kakkokari-gtyih Sep 26, 2024
ace9e4e
Merge branch 'develop' into feat-setup-initial-password
kakkokari-gtyih Sep 26, 2024
beb9ed9
Merge branch 'develop' into feat-setup-initial-password
kakkokari-gtyih Sep 26, 2024
3302fac
Merge branch 'develop' into pr/14626
syuilo Oct 3, 2024
aab74bf
Update CHANGELOG.md
syuilo Oct 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .config/cypress-devcontainer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@
# Misskey configuration
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

# ┌────────────────────────┐
#───┘ Initial Setup Password └─────────────────────────────────────────────────────

# Password to initiate setting up admin account.
# It will not be used after the initial setup is complete.
#
# Be sure to change this when you set up Misskey via the Internet.
#
# The provider of the service who sets up Misskey on behalf of the customer should
# set this value to something unique when generating the Misskey config file,
# and provide it to the customer.
initialPassword: example_password_please_change_this_or_you_will_get_hacked

# ┌─────┐
#───┘ URL └─────────────────────────────────────────────────────

Expand Down
13 changes: 13 additions & 0 deletions .config/example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,19 @@
#
# publishTarballInsteadOfProvideRepositoryUrl: true

# ┌────────────────────────┐
#───┘ Initial Setup Password └─────────────────────────────────────────────────────

# Password to initiate setting up admin account.
# It will not be used after the initial setup is complete.
#
# Be sure to change this when you set up Misskey via the Internet.
#
# The provider of the service who sets up Misskey on behalf of the customer should
# set this value to something unique when generating the Misskey config file,
# and provide it to the customer.
initialPassword: example_password_please_change_this_or_you_will_get_hacked

# ┌─────┐
#───┘ URL └─────────────────────────────────────────────────────

Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
## 2024.10.0

### Note
- サーバー初期設定時に使用する初期パスワードを設定できるようになりました。今後Misskeyサーバーを新たに設置する際には、初回の起動前にコンフィグファイルの`initialPassword`を必ず変更してください。(すでに初期設定を完了しているサーバーについては、この変更に伴い対応する必要はありません)
ホスティングサービスを運営している場合は、コンフィグファイルを構築する際に`initialPassword`をランダムな値に設定し、ユーザーに通知するようにしてください。

### General
- Feat: サーバー初期設定時に初期パスワードを設定できるように
- Enhance: セキュリティ向上のため、サインイン時もCAPTCHAを求めるようになりました
- Enhance: 依存関係の更新
- Enhance: l10nの更新
Expand Down
1 change: 1 addition & 0 deletions cypress/e2e/basic.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ describe('Before setup instance', () => {

cy.intercept('POST', '/api/admin/accounts/create').as('signup');

cy.get('[data-cy-admin-initial-password] input').type('example_password_please_change_this_or_you_will_get_hacked');
cy.get('[data-cy-admin-username] input').type('admin');
cy.get('[data-cy-admin-password] input').type('admin1234');
cy.get('[data-cy-admin-ok]').click();
Expand Down
14 changes: 14 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,20 @@ export interface Locale extends ILocale {
* パスワード
*/
"password": string;
/**
* 初期設定開始用パスワード
*/
"initialPasswordForSetup": string;
/**
* 初期設定開始用のパスワードが違います。
*/
"initialPasswordIsIncorrect": string;
/**
* Misskeyを自分でインストールした場合は、設定ファイルに入力したパスワードを使用してください。
* Misskeyのホスティングサービスなどを使用している場合は、提供されたパスワードを使用してください。
* パスワードを設定していない場合は、空欄にしたまま続行してください。
*/
"initialPasswordForSetupDescription": string;
/**
* パスワードを忘れた
*/
Expand Down
3 changes: 3 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ search: "検索"
notifications: "通知"
username: "ユーザー名"
password: "パスワード"
initialPasswordForSetup: "初期設定開始用パスワード"
initialPasswordIsIncorrect: "初期設定開始用のパスワードが違います。"
initialPasswordForSetupDescription: "Misskeyを自分でインストールした場合は、設定ファイルに入力したパスワードを使用してください。\nMisskeyのホスティングサービスなどを使用している場合は、提供されたパスワードを使用してください。\nパスワードを設定していない場合は、空欄にしたまま続行してください。"
forgotPassword: "パスワードを忘れた"
fetchingAsApObject: "連合に照会中"
ok: "OK"
Expand Down
4 changes: 4 additions & 0 deletions packages/backend/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ type Source = {

publishTarballInsteadOfProvideRepositoryUrl?: boolean;

initialPassword?: string;

proxy?: string;
proxySmtp?: string;
proxyBypassHosts?: string[];
Expand Down Expand Up @@ -152,6 +154,7 @@ export type Config = {

version: string;
publishTarballInsteadOfProvideRepositoryUrl: boolean;
initialPassword: string | undefined;
host: string;
hostname: string;
scheme: string;
Expand Down Expand Up @@ -232,6 +235,7 @@ export function loadConfig(): Config {
return {
version,
publishTarballInsteadOfProvideRepositoryUrl: !!config.publishTarballInsteadOfProvideRepositoryUrl,
initialPassword: config.initialPassword,
url: url.origin,
port: config.port ?? parseInt(process.env.PORT ?? '', 10),
socket: config.socket,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,27 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { InstanceActorService } from '@/core/InstanceActorService.js';
import { localUsernameSchema, passwordSchema } from '@/models/User.js';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import { ApiError } from '@/server/api/error.js';
import { Packed } from '@/misc/json-schema.js';

export const meta = {
tags: ['admin'],

errors: {
accessDenied: {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: '1fb7cb09-d46a-4fff-b8df-057708cce513',
},

wrongInitialPassword: {
message: 'Initial password is incorrect.',
code: 'INCORRECT_INITIAL_PASSWORD',
id: '97147c55-1ae1-4f6f-91d6-e1c3e0e76d62',
},
},

res: {
type: 'object',
optional: false, nullable: false,
Expand All @@ -35,13 +51,17 @@ export const paramDef = {
properties: {
username: localUsernameSchema,
password: passwordSchema,
initialPassword: { type: 'string', nullable: true },
},
required: ['username', 'password'],
} as const;

@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
constructor(
@Inject(DI.config)
private config: Config,

@Inject(DI.usersRepository)
private usersRepository: UsersRepository,

Expand All @@ -52,7 +72,23 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
super(meta, paramDef, async (ps, _me, token) => {
const me = _me ? await this.usersRepository.findOneByOrFail({ id: _me.id }) : null;
const realUsers = await this.instanceActorService.realLocalUsersPresent();
if ((realUsers && !me?.isRoot) || token !== null) throw new Error('access denied');

if (!realUsers && me == null && token == null) {
// 初回セットアップの場合
if (this.config.initialPassword != null) {
// 初期パスワードが設定されている場合
if (ps.initialPassword !== this.config.initialPassword) {
// 初期パスワードが違う場合
throw new ApiError(meta.errors.wrongInitialPassword);
}
} else if (ps.initialPassword != null && ps.initialPassword.trim() !== '') {
// 初期パスワードが設定されていないのに初期パスワードが入力された場合
throw new ApiError(meta.errors.wrongInitialPassword);
}
} else if ((realUsers && !me?.isRoot) || token !== null) {
// 初回セットアップではなく、管理者でない場合 or 外部トークンを使用している場合
throw new ApiError(meta.errors.accessDenied);
}

const { account, secret } = await this.signupService.signup({
username: ps.username,
Expand Down
26 changes: 22 additions & 4 deletions packages/frontend/src/pages/welcome.setup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
<div class="_gaps_m" style="padding: 32px;">
<div>{{ i18n.ts.intro }}</div>
<MkInput v-model="initialPassword" type="password" data-cy-admin-initial-password>
<template #label>{{ i18n.ts.initialPasswordForSetup }} <div v-tooltip:dialog="i18n.ts.initialPasswordForSetupDescription" class="_button _help"><i class="ti ti-help-circle"></i></div></template>
<template #prefix><i class="ti ti-lock"></i></template>
</MkInput>
<MkInput v-model="username" pattern="^[a-zA-Z0-9_]{1,20}$" :spellcheck="false" required data-cy-admin-username>
<template #label>{{ i18n.ts.username }}</template>
<template #prefix>@</template>
Expand Down Expand Up @@ -47,6 +51,7 @@ import MkAnimBg from '@/components/MkAnimBg.vue';

const username = ref('');
const password = ref('');
const initialPassword = ref('');
const submitting = ref(false);

function submit() {
Expand All @@ -56,14 +61,27 @@ function submit() {
misskeyApi('admin/accounts/create', {
username: username.value,
password: password.value,
initialPassword: initialPassword.value === '' ? null : initialPassword.value,
}).then(res => {
return login(res.token);
}).catch(() => {
}).catch((err) => {
submitting.value = false;

let title = i18n.ts.somethingHappened;
let text = err.message + '\n' + err.id;

if (err.code === 'ACCESS_DENIED') {
title = i18n.ts.permissionDeniedError;
text = i18n.ts.operationForbidden;
} else if (err.code === 'INCORRECT_INITIAL_PASSWORD') {
title = i18n.ts.permissionDeniedError;
text = i18n.ts.incorrectPassword;
}

os.alert({
type: 'error',
text: i18n.ts.somethingHappened,
title,
text,
});
});
}
Expand All @@ -74,8 +92,8 @@ function submit() {
min-height: 100svh;
padding: 32px 32px 64px 32px;
box-sizing: border-box;
display: grid;
place-content: center;
display: grid;
place-content: center;
}

.form {
Expand Down
1 change: 1 addition & 0 deletions packages/misskey-js/src/autogen/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5611,6 +5611,7 @@ export type operations = {
'application/json': {
username: string;
password: string;
initialPassword?: string | null;
};
};
};
Expand Down
Loading