Reviewed-on: #120pull/121/head
parent
a3501cab86
commit
645f0390bc
@ -0,0 +1,187 @@
|
||||
variables:
|
||||
- &scw-secrets
|
||||
- SCW_ACCESS_KEY
|
||||
- SCW_SECRET_KEY
|
||||
- SCW_DEFAULT_ORGANIZATION_ID
|
||||
- &setup-hex "mix local.hex --force && mix local.rebar --force"
|
||||
- &on-release
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
branch:
|
||||
- develop
|
||||
- stable
|
||||
- refs/tags/v*
|
||||
- refs/tags/stable-*
|
||||
- &on-point-release
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
branch:
|
||||
- develop
|
||||
- stable
|
||||
- &on-pr-open
|
||||
when:
|
||||
event:
|
||||
- pull_request
|
||||
|
||||
- &tag-build "export BUILD_TAG=$${CI_COMMIT_TAG:-\"$CI_COMMIT_BRANCH\"} && export PLEROMA_BUILD_BRANCH=$BUILD_TAG"
|
||||
|
||||
- &clean "(rm -rf release || true) && (rm -rf _build || true) && (rm -rf /root/.mix)"
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:13
|
||||
when:
|
||||
event:
|
||||
- pull_request
|
||||
environment:
|
||||
POSTGRES_DB: pleroma_test
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
|
||||
pipeline:
|
||||
lint:
|
||||
<<: *on-pr-open
|
||||
image: akkoma/ci-base:latest
|
||||
commands:
|
||||
- mix local.hex --force
|
||||
- mix local.rebar --force
|
||||
- mix format --check-formatted
|
||||
|
||||
build:
|
||||
image: akkoma/ci-base:latest
|
||||
<<: *on-pr-open
|
||||
environment:
|
||||
MIX_ENV: test
|
||||
POSTGRES_DB: pleroma_test
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
DB_HOST: postgres
|
||||
commands:
|
||||
- mix local.hex --force
|
||||
- mix local.rebar --force
|
||||
- mix deps.get
|
||||
- mix compile
|
||||
|
||||
test:
|
||||
image: akkoma/ci-base:latest
|
||||
<<: *on-pr-open
|
||||
environment:
|
||||
MIX_ENV: test
|
||||
POSTGRES_DB: pleroma_test
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
DB_HOST: postgres
|
||||
commands:
|
||||
- mix local.hex --force
|
||||
- mix local.rebar --force
|
||||
- mix deps.get
|
||||
- mix compile
|
||||
- mix ecto.drop -f -q
|
||||
- mix ecto.create
|
||||
- mix ecto.migrate
|
||||
- mix test --preload-modules --exclude erratic --exclude federated --max-cases 4
|
||||
|
||||
# Canonical amd64
|
||||
ubuntu22:
|
||||
image: hexpm/elixir:1.13.4-erlang-25.0.2-ubuntu-jammy-20220428
|
||||
<<: *on-release
|
||||
environment:
|
||||
MIX_ENV: prod
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
commands:
|
||||
- rm config/emoji.txt
|
||||
- apt-get update && apt-get install -y cmake libmagic-dev rclone zip imagemagick libmagic-dev git build-essential g++ wget
|
||||
- *clean
|
||||
- echo "import Config" > config/prod.secret.exs
|
||||
- *setup-hex
|
||||
- *tag-build
|
||||
- mix deps.get --only prod
|
||||
- mix release --path release
|
||||
- zip akkoma-amd64.zip -r release
|
||||
|
||||
release-ubuntu22:
|
||||
image: akkoma/releaser
|
||||
<<: *on-release
|
||||
secrets: *scw-secrets
|
||||
commands:
|
||||
- export SOURCE=akkoma-amd64.zip
|
||||
- export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64.zip
|
||||
- /bin/sh /entrypoint.sh
|
||||
environment:
|
||||
SOURCE: akkoma-amd64.zip
|
||||
DEST: scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64.zip
|
||||
|
||||
debian-bullseye:
|
||||
image: elixir:1.13.4
|
||||
<<: *on-release
|
||||
environment:
|
||||
MIX_ENV: prod
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
commands:
|
||||
- apt-get update && apt-get install -y cmake libmagic-dev rclone zip imagemagick libmagic-dev git build-essential gcc make g++ wget
|
||||
- *clean
|
||||
- echo "import Config" > config/prod.secret.exs
|
||||
- *setup-hex
|
||||
- *tag-build
|
||||
- mix deps.get --only prod
|
||||
- mix release --path release
|
||||
- zip akkoma-amd64.zip -r release
|
||||
|
||||
release-debian:
|
||||
image: akkoma/releaser
|
||||
<<: *on-release
|
||||
secrets: *scw-secrets
|
||||
commands:
|
||||
- export SOURCE=akkoma-amd64.zip
|
||||
- export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-debian-bullseye.zip
|
||||
- /bin/sh /entrypoint.sh
|
||||
|
||||
# Canonical amd64-musl
|
||||
musl:
|
||||
image: elixir:1.13.4-alpine
|
||||
<<: *on-release
|
||||
environment:
|
||||
MIX_ENV: prod
|
||||
commands:
|
||||
- apk add git gcc g++ musl-dev make cmake file-dev rclone wget zip imagemagick
|
||||
- *clean
|
||||
- *setup-hex
|
||||
- mix deps.clean --all
|
||||
- *tag-build
|
||||
- mix deps.get --only prod
|
||||
- mix release --path release
|
||||
- zip akkoma-amd64-musl.zip -r release
|
||||
|
||||
release-musl:
|
||||
image: akkoma/releaser
|
||||
<<: *on-release
|
||||
secrets: *scw-secrets
|
||||
commands:
|
||||
- export SOURCE=akkoma-amd64-musl.zip
|
||||
- export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64-musl.zip
|
||||
- /bin/sh /entrypoint.sh
|
||||
|
||||
docs:
|
||||
<<: *on-point-release
|
||||
secrets:
|
||||
- SCW_ACCESS_KEY
|
||||
- SCW_SECRET_KEY
|
||||
- SCW_DEFAULT_ORGANIZATION_ID
|
||||
environment:
|
||||
CI: "true"
|
||||
image: python:3.10-slim
|
||||
commands:
|
||||
- apt-get update && apt-get install -y rclone wget git zip
|
||||
- wget https://github.com/scaleway/scaleway-cli/releases/download/v2.5.1/scaleway-cli_2.5.1_linux_amd64
|
||||
- mv scaleway-cli_2.5.1_linux_amd64 scaleway-cli
|
||||
- chmod +x scaleway-cli
|
||||
- ./scaleway-cli object config install type=rclone
|
||||
- cd docs
|
||||
- pip install -r requirements.txt
|
||||
- mkdocs build
|
||||
- zip -r docs.zip site/*
|
||||
- cd site
|
||||
- rclone copy . scaleway:akkoma-docs/$CI_COMMIT_BRANCH/
|
@ -1,27 +0,0 @@
|
||||
pipeline:
|
||||
build:
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
branch:
|
||||
- develop
|
||||
- stable
|
||||
secrets:
|
||||
- SCW_ACCESS_KEY
|
||||
- SCW_SECRET_KEY
|
||||
- SCW_DEFAULT_ORGANIZATION_ID
|
||||
environment:
|
||||
CI: "true"
|
||||
image: python:3.10-slim
|
||||
commands:
|
||||
- apt-get update && apt-get install -y rclone wget git zip
|
||||
- wget https://github.com/scaleway/scaleway-cli/releases/download/v2.5.1/scaleway-cli_2.5.1_linux_amd64
|
||||
- mv scaleway-cli_2.5.1_linux_amd64 scaleway-cli
|
||||
- chmod +x scaleway-cli
|
||||
- ./scaleway-cli object config install type=rclone
|
||||
- cd docs
|
||||
- pip install -r requirements.txt
|
||||
- mkdocs build
|
||||
- zip -r docs.zip site/*
|
||||
- cd site
|
||||
- rclone copy . scaleway:akkoma-docs/$CI_COMMIT_BRANCH/
|
@ -1,59 +0,0 @@
|
||||
variables:
|
||||
- &scw-secrets
|
||||
- SCW_ACCESS_KEY
|
||||
- SCW_SECRET_KEY
|
||||
- SCW_DEFAULT_ORGANIZATION_ID
|
||||
- &setup-scw-s3 "wget https://github.com/scaleway/scaleway-cli/releases/download/v2.5.1/scaleway-cli_2.5.1_linux_amd64 && mv scaleway-cli_2.5.1_linux_amd64 scaleway-cli && chmod +x scaleway-cli && ./scaleway-cli object config install type=rclone"
|
||||
|
||||
- &setup-hex "mix local.hex --force && mix local.rebar --force"
|
||||
- &build-on
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
branch:
|
||||
- develop
|
||||
- stable
|
||||
- refs/tags/v*
|
||||
- refs/tags/stable-*
|
||||
- &tag-build 'export BUILD_TAG=$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"} && export PLEROMA_BUILD_BRANCH=$BUILD_TAG'
|
||||
|
||||
- &clean "(rm -rf release || true) && (rm -rf _build || true) && (rm -rf /root/.mix) && (rm scaleway-cli || true)"
|
||||
|
||||
|
||||
pipeline:
|
||||
glibc:
|
||||
image: elixir:1.13
|
||||
<<: *build-on
|
||||
secrets: *scw-secrets
|
||||
environment:
|
||||
MIX_ENV: prod
|
||||
commands:
|
||||
- apt-get update && apt-get install -y cmake libmagic-dev rclone zip imagemagick libmagic-dev git
|
||||
- *clean
|
||||
- *setup-scw-s3
|
||||
- echo "import Mix.Config" > config/prod.secret.exs
|
||||
- *setup-hex
|
||||
- *tag-build
|
||||
- mix deps.get --only prod
|
||||
- mix release --path release
|
||||
- zip akkoma-amd64.zip -r release
|
||||
- rclone copyto akkoma-amd64.zip scaleway:akkoma-updates/$BUILD_TAG/akkoma-amd64.zip
|
||||
|
||||
musl:
|
||||
image: elixir:1.13-alpine
|
||||
<<: *build-on
|
||||
secrets: *scw-secrets
|
||||
environment:
|
||||
MIX_ENV: prod
|
||||
commands:
|
||||
- apk add git gcc g++ musl-dev make cmake file-dev rclone wget zip imagemagick
|
||||
- *clean
|
||||
- *setup-scw-s3
|
||||
- *setup-hex
|
||||
- mix deps.clean --all
|
||||
- *tag-build
|
||||
- mix deps.get --only prod
|
||||
- mix release --path release
|
||||
- zip akkoma-amd64.zip -r release
|
||||
- rclone copyto akkoma-amd64.zip scaleway:akkoma-updates/$BUILD_TAG/akkoma-amd64-musl.zip
|
@ -1,59 +0,0 @@
|
||||
matrix:
|
||||
ELIXIR_VERSION:
|
||||
- 1.13
|
||||
|
||||
pipeline:
|
||||
lint:
|
||||
when:
|
||||
event:
|
||||
- pull_request
|
||||
image: pleromaforkci/ci-base:1.13
|
||||
commands:
|
||||
- mix local.hex --force
|
||||
- mix local.rebar --force
|
||||
- mix format --check-formatted
|
||||
|
||||
build:
|
||||
image: pleromaforkci/ci-base:${ELIXIR_VERSION}
|
||||
when:
|
||||
event:
|
||||
- pull_request
|
||||
environment:
|
||||
MIX_ENV: test
|
||||
commands:
|
||||
- mix local.hex --force
|
||||
- mix local.rebar --force
|
||||
- mix deps.get
|
||||
- mix compile
|
||||
|
||||
test:
|
||||
group: test
|
||||
image: pleromaforkci/ci-base:${ELIXIR_VERSION}
|
||||
when:
|
||||
event:
|
||||
- pull_request
|
||||
environment:
|
||||
MIX_ENV: test
|
||||
POSTGRES_DB: pleroma_test
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
DB_HOST: postgres
|
||||
commands:
|
||||
- mix local.hex --force
|
||||
- mix local.rebar --force
|
||||
- mix deps.get
|
||||
- mix ecto.drop -f -q
|
||||
- mix ecto.create
|
||||
- mix ecto.migrate
|
||||
- mix test --preload-modules --exclude erratic --exclude federated --max-cases 4
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:13
|
||||
when:
|
||||
event:
|
||||
- pull_request
|
||||
environment:
|
||||
POSTGRES_DB: pleroma_test
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
@ -0,0 +1,129 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Auth.LDAPAuthenticator do
|
||||
alias Pleroma.User
|
||||
|
||||
require Logger
|
||||
|
||||
import Pleroma.Web.Auth.Helpers, only: [fetch_credentials: 1, fetch_user: 1]
|
||||
|
||||
@behaviour Pleroma.Web.Auth.Authenticator
|
||||
@base Pleroma.Web.Auth.PleromaAuthenticator
|
||||
|
||||
@connection_timeout 10_000
|
||||
@search_timeout 10_000
|
||||
|
||||
defdelegate get_registration(conn), to: @base
|
||||
defdelegate create_from_registration(conn, registration), to: @base
|
||||
defdelegate handle_error(conn, error), to: @base
|
||||
defdelegate auth_template, to: @base
|
||||
defdelegate oauth_consumer_template, to: @base
|
||||
|
||||
def get_user(%Plug.Conn{} = conn) do
|
||||
with {:ldap, true} <- {:ldap, Pleroma.Config.get([:ldap, :enabled])},
|
||||
{:ok, {name, password}} <- fetch_credentials(conn),
|
||||
%User{} = user <- ldap_user(name, password) do
|
||||
{:ok, user}
|
||||
else
|
||||
{:ldap, _} ->
|
||||
@base.get_user(conn)
|
||||
|
||||
error ->
|
||||
error
|
||||
end
|
||||
end
|
||||
|
||||
defp ldap_user(name, password) do
|
||||
ldap = Pleroma.Config.get(:ldap, [])
|
||||
host = Keyword.get(ldap, :host, "localhost")
|
||||
port = Keyword.get(ldap, :port, 389)
|
||||
ssl = Keyword.get(ldap, :ssl, false)
|
||||
sslopts = Keyword.get(ldap, :sslopts, [])
|
||||
|
||||
options =
|
||||
[{:port, port}, {:ssl, ssl}, {:timeout, @connection_timeout}] ++
|
||||
if sslopts != [], do: [{:sslopts, sslopts}], else: []
|
||||
|
||||
case :eldap.open([to_charlist(host)], options) do
|
||||
{:ok, connection} ->
|
||||
try do
|
||||
if Keyword.get(ldap, :tls, false) do
|
||||
:application.ensure_all_started(:ssl)
|
||||
|
||||
case :eldap.start_tls(
|
||||
connection,
|
||||
Keyword.get(ldap, :tlsopts, []),
|
||||
@connection_timeout
|
||||
) do
|
||||
:ok ->
|
||||
:ok
|
||||
|
||||
error ->
|
||||
Logger.error("Could not start TLS: #{inspect(error)}")
|
||||
end
|
||||
end
|
||||
|
||||
bind_user(connection, ldap, name, password)
|
||||
after
|
||||
:eldap.close(connection)
|
||||
end
|
||||
|
||||
{:error, error} ->
|
||||
Logger.error("Could not open LDAP connection: #{inspect(error)}")
|
||||
{:error, {:ldap_connection_error, error}}
|
||||
end
|
||||
end
|
||||
|
||||
defp bind_user(connection, ldap, name, password) do
|
||||
uid = Keyword.get(ldap, :uid, "cn")
|
||||
base = Keyword.get(ldap, :base)
|
||||
|
||||
case :eldap.simple_bind(connection, "#{uid}=#{name},#{base}", password) do
|
||||
:ok ->
|
||||
case fetch_user(name) do
|
||||
%User{} = user ->
|
||||
user
|
||||
|
||||
_ ->
|
||||
register_user(connection, base, uid, name)
|
||||
end
|
||||
|
||||
error ->
|
||||
error
|
||||
end
|
||||
end
|
||||
|
||||
defp register_user(connection, base, uid, name) do
|
||||
case :eldap.search(connection, [
|
||||
{:base, to_charlist(base)},
|
||||
{:filter, :eldap.equalityMatch(to_charlist(uid), to_charlist(name))},
|
||||
{:scope, :eldap.wholeSubtree()},
|
||||
{:timeout, @search_timeout}
|
||||
]) do
|
||||
{:ok, {:eldap_search_result, [{:eldap_entry, _, attributes}], _}} ->
|
||||
params = %{
|
||||
name: name,
|
||||
nickname: name,
|
||||
password: nil
|
||||
}
|
||||
|
||||
params =
|
||||
case List.keyfind(attributes, 'mail', 0) do
|
||||
{_, [mail]} -> Map.put_new(params, :email, :erlang.list_to_binary(mail))
|
||||
_ -> params
|
||||
end
|
||||
|
||||
changeset = User.register_changeset_ldap(%User{}, params)
|
||||
|
||||
case User.register(changeset) do
|
||||
{:ok, user} -> user
|
||||
error -> error
|
||||
end
|
||||
|
||||
error ->
|
||||
error
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,135 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
import Pleroma.Factory
|
||||
import Mock
|
||||
|
||||
@skip if !Code.ensure_loaded?(:eldap), do: :skip
|
||||
|
||||
setup_all do: clear_config([:ldap, :enabled], true)
|
||||
|
||||
setup_all do: clear_config(Pleroma.Web.Auth.Authenticator, Pleroma.Web.Auth.LDAPAuthenticator)
|
||||
|
||||
@tag @skip
|
||||
test "authorizes the existing user using LDAP credentials" do
|
||||
password = "testpassword"
|
||||
user = insert(:user, password_hash: Pleroma.Password.Pbkdf2.hash_pwd_salt(password))
|
||||
app = insert(:oauth_app, scopes: ["read", "write"])
|
||||
|
||||
host = Pleroma.Config.get([:ldap, :host]) |> to_charlist
|
||||
port = Pleroma.Config.get([:ldap, :port])
|
||||
|
||||
with_mocks [
|
||||
{:eldap, [],
|
||||
[
|
||||
open: fn [^host], [{:port, ^port}, {:ssl, false} | _] -> {:ok, self()} end,
|
||||
simple_bind: fn _connection, _dn, ^password -> :ok end,
|
||||
close: fn _connection ->
|
||||
send(self(), :close_connection)
|
||||
:ok
|
||||
end
|
||||
]}
|
||||
] do
|
||||
conn =
|
||||
build_conn()
|
||||
|> post("/oauth/token", %{
|
||||
"grant_type" => "password",
|
||||
"username" => user.nickname,
|
||||
"password" => password,
|
||||
"client_id" => app.client_id,
|
||||
"client_secret" => app.client_secret
|
||||
})
|
||||
|
||||
assert %{"access_token" => token} = json_response(conn, 200)
|
||||
|
||||
token = Repo.get_by(Token, token: token)
|
||||
|
||||
assert token.user_id == user.id
|
||||
assert_received :close_connection
|
||||
end
|
||||
end
|
||||
|
||||
@tag @skip
|
||||
test "creates a new user after successful LDAP authorization" do
|
||||
password = "testpassword"
|
||||
user = build(:user)
|
||||
app = insert(:oauth_app, scopes: ["read", "write"])
|
||||
|
||||
host = Pleroma.Config.get([:ldap, :host]) |> to_charlist
|
||||
port = Pleroma.Config.get([:ldap, :port])
|
||||
|
||||
with_mocks [
|
||||
{:eldap, [],
|
||||
[
|
||||
open: fn [^host], [{:port, ^port}, {:ssl, false} | _] -> {:ok, self()} end,
|
||||
simple_bind: fn _connection, _dn, ^password -> :ok end,
|
||||
equalityMatch: fn _type, _value -> :ok end,
|
||||
wholeSubtree: fn -> :ok end,
|
||||
search: fn _connection, _options ->
|
||||
{:ok, {:eldap_search_result, [{:eldap_entry, '', []}], []}}
|
||||
end,
|
||||
close: fn _connection ->
|
||||
send(self(), :close_connection)
|
||||
:ok
|
||||
end
|
||||
]}
|
||||
] do
|
||||
conn =
|
||||
build_conn()
|
||||
|> post("/oauth/token", %{
|
||||
"grant_type" => "password",
|
||||
"username" => user.nickname,
|
||||
"password" => password,
|
||||
"client_id" => app.client_id,
|
||||
"client_secret" => app.client_secret
|
||||
})
|
||||
|
||||
assert %{"access_token" => token} = json_response(conn, 200)
|
||||
|
||||
token = Repo.get_by(Token, token: token) |> Repo.preload(:user)
|
||||
|
||||
assert token.user.nickname == user.nickname
|
||||
assert_received :close_connection
|
||||
end
|
||||
end
|
||||
|
||||
@tag @skip
|
||||
test "disallow authorization for wrong LDAP credentials" do
|
||||
password = "testpassword"
|
||||
user = insert(:user, password_hash: Pleroma.Password.Pbkdf2.hash_pwd_salt(password))
|
||||
app = insert(:oauth_app, scopes: ["read", "write"])
|
||||
|
||||
host = Pleroma.Config.get([:ldap, :host]) |> to_charlist
|
||||
port = Pleroma.Config.get([:ldap, :port])
|
||||
|
||||
with_mocks [
|
||||
{:eldap, [],
|
||||
[
|
||||
open: fn [^host], [{:port, ^port}, {:ssl, false} | _] -> {:ok, self()} end,
|
||||
simple_bind: fn _connection, _dn, ^password -> {:error, :invalidCredentials} end,
|
||||
close: fn _connection ->
|
||||
send(self(), :close_connection)
|
||||
:ok
|
||||
end
|
||||
]}
|
||||
] do
|
||||
conn =
|
||||
build_conn()
|
||||
|> post("/oauth/token", %{
|
||||
"grant_type" => "password",
|
||||
"username" => user.nickname,
|
||||
"password" => password,
|
||||
"client_id" => app.client_id,
|
||||
"client_secret" => app.client_secret
|
||||
})
|
||||
|
||||
assert %{"error" => "Invalid credentials"} = json_response(conn, 400)
|
||||
assert_received :close_connection
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in new issue