Merge branch 'master' into dwarf-4

This commit is contained in:
mergify[bot] 2022-02-21 09:58:06 +00:00 committed by GitHub
commit ed61487082
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
128 changed files with 1531 additions and 1430 deletions

View File

@ -117,8 +117,11 @@ if (OS_DARWIN)
endif ()
add_library(_jemalloc ${SRCS})
# First include jemalloc-cmake files, to override anything that jemalloc has.
# (for example if you were trying to build jemalloc inside contrib/jemalloc you
# will have some files that may be out of date)
target_include_directories(_jemalloc PUBLIC include)
target_include_directories(_jemalloc PRIVATE "${LIBRARY_DIR}/include")
target_include_directories(_jemalloc SYSTEM PUBLIC include)
set (JEMALLOC_INCLUDE_PREFIX)
# OS_

View File

@ -12,5 +12,6 @@ The following external authenticators and directories are supported:
- [LDAP](./ldap.md#external-authenticators-ldap) [Authenticator](./ldap.md#ldap-external-authenticator) and [Directory](./ldap.md#ldap-external-user-directory)
- Kerberos [Authenticator](./kerberos.md#external-authenticators-kerberos)
- [SSL X.509 authentication](./ssl-x509.md#ssl-external-authentication)
[Original article](https://clickhouse.com/docs/en/operations/external-authenticators/index/) <!--hide-->

View File

@ -0,0 +1,24 @@
# SSL X.509 certificate authentication {#ssl-external-authentication}
[SSL 'strict' option](../server-configuration-parameters/settings.md#server_configuration_parameters-openssl) enables mandatory certificate validation for the incoming connections. In this case, only connections with trusted certificates can be established. Connections with untrusted certificates will be rejected. Thus, certificate validation allows to uniquely authenticate an incoming connection. `Common Name` field of the certificate is used to identify connected user. This allows to associate multiple certificates with the same user. Additionally, reissuing and revoking of the certificates does not affect the ClickHouse configuration.
To enable SSL certificate authentication, a list of `Common Name`'s for each ClickHouse user must be sspecified in the settings file `config.xml `:
**Example**
```xml
<clickhouse>
<!- ... -->
<users>
<user_name>
<certificates>
<common_name>host.domain.com:example_user</common_name>
<common_name>host.domain.com:example_user_dev</common_name>
<!-- More names -->
</certificates>
<!-- Other settings -->
</user_name>
</users>
</clickhouse>
```
For the SSL [`chain of trust`](https://en.wikipedia.org/wiki/Chain_of_trust) to work correctly, it is also important to make sure that the [`caConfig`](../server-configuration-parameters/settings.md#server_configuration_parameters-openssl) parameter is configured properly.

View File

@ -0,0 +1 @@
../../../en/operations/external-authenticators/ssl-x509.md

View File

@ -12,5 +12,6 @@ ClickHouse поддерживает аутентификацию и управл
- [LDAP](./ldap.md#external-authenticators-ldap) [аутентификатор](./ldap.md#ldap-external-authenticator) и [каталог](./ldap.md#ldap-external-user-directory)
- Kerberos [аутентификатор](./kerberos.md#external-authenticators-kerberos)
- [SSL X.509 аутентификация](./ssl-x509.md#ssl-external-authentication)
[Оригинальная статья](https://clickhouse.com/docs/ru/operations/external-authenticators/index/) <!--hide-->

View File

@ -0,0 +1,24 @@
# Аутентификация по сертификату SSL X.509 {#ssl-external-authentication}
[Опция 'strict'](../server-configuration-parameters/settings.md#server_configuration_parameters-openssl) включает обязательную проверку сертификатов входящих соединений в библиотеке `SSL`. В этом случае могут быть установлены только соединения, представившие действительный сертификат. Соединения с недоверенными сертификатами будут отвергнуты. Таким образом, проверка сертификата позволяет однозначно аутентифицировать входящее соединение. Идентификация пользователя осуществляется по полю `Common Name` сертификата. Это позволяет ассоциировать несколько сертификатов с одним и тем же пользователем. Дополнительно, перевыпуск и отзыв сертификата не требуют изменения конфигурации ClickHouse.
Для включения аутентификации по SSL сертификату, необходимо указать список `Common Name` для каждого пользователя ClickHouse в файле настройки `config.xml`:
**Example**
```xml
<clickhouse>
<!- ... -->
<users>
<user_name>
<certificates>
<common_name>host.domain.com:example_user</common_name>
<common_name>host.domain.com:example_user_dev</common_name>
<!-- More names -->
</certificates>
<!-- Other settings -->
</user_name>
</users>
</clickhouse>
```
Для правильной работы SSL [`chain of trust`](https://en.wikipedia.org/wiki/Chain_of_trust) важно также убедиться в правильной настройке параметра [`caConfig`](../server-configuration-parameters/settings.md#server_configuration_parameters-openssl)

View File

@ -0,0 +1 @@
../../../en/operations/external-authenticators/ssl-x509.md

View File

@ -87,6 +87,9 @@ bool Authentication::areCredentialsValid(const Credentials & credentials, const
case AuthenticationType::KERBEROS:
return external_authenticators.checkKerberosCredentials(auth_data.getKerberosRealm(), *gss_acceptor_context);
case AuthenticationType::SSL_CERTIFICATE:
throw Authentication::Require<BasicCredentials>("ClickHouse X.509 Authentication");
case AuthenticationType::MAX:
break;
}
@ -110,6 +113,9 @@ bool Authentication::areCredentialsValid(const Credentials & credentials, const
case AuthenticationType::KERBEROS:
throw Authentication::Require<BasicCredentials>("ClickHouse Basic Authentication");
case AuthenticationType::SSL_CERTIFICATE:
throw Authentication::Require<BasicCredentials>("ClickHouse X.509 Authentication");
case AuthenticationType::MAX:
break;
}
@ -137,6 +143,31 @@ bool Authentication::areCredentialsValid(const Credentials & credentials, const
case AuthenticationType::KERBEROS:
throw Authentication::Require<GSSAcceptorContext>(auth_data.getKerberosRealm());
case AuthenticationType::SSL_CERTIFICATE:
throw Authentication::Require<BasicCredentials>("ClickHouse X.509 Authentication");
case AuthenticationType::MAX:
break;
}
}
if (const auto * ssl_certificate_credentials = typeid_cast<const SSLCertificateCredentials *>(&credentials))
{
switch (auth_data.getType())
{
case AuthenticationType::NO_PASSWORD:
case AuthenticationType::PLAINTEXT_PASSWORD:
case AuthenticationType::SHA256_PASSWORD:
case AuthenticationType::DOUBLE_SHA1_PASSWORD:
case AuthenticationType::LDAP:
throw Authentication::Require<BasicCredentials>("ClickHouse Basic Authentication");
case AuthenticationType::KERBEROS:
throw Authentication::Require<GSSAcceptorContext>(auth_data.getKerberosRealm());
case AuthenticationType::SSL_CERTIFICATE:
return auth_data.getSSLCertificateCommonNames().contains(ssl_certificate_credentials->getCommonName());
case AuthenticationType::MAX:
break;
}

View File

@ -15,7 +15,6 @@ namespace ErrorCodes
class Credentials;
class ExternalAuthenticators;
/// TODO: Try to move this checking to Credentials.
struct Authentication
{

View File

@ -59,6 +59,11 @@ const AuthenticationTypeInfo & AuthenticationTypeInfo::get(AuthenticationType ty
static const auto info = make_info("KERBEROS");
return info;
}
case AuthenticationType::SSL_CERTIFICATE:
{
static const auto info = make_info("SSL_CERTIFICATE");
return info;
}
case AuthenticationType::MAX:
break;
}
@ -92,7 +97,8 @@ AuthenticationData::Digest AuthenticationData::Util::encodeSHA1(const std::strin
bool operator ==(const AuthenticationData & lhs, const AuthenticationData & rhs)
{
return (lhs.type == rhs.type) && (lhs.password_hash == rhs.password_hash)
&& (lhs.ldap_server_name == rhs.ldap_server_name) && (lhs.kerberos_realm == rhs.kerberos_realm);
&& (lhs.ldap_server_name == rhs.ldap_server_name) && (lhs.kerberos_realm == rhs.kerberos_realm)
&& (lhs.ssl_certificate_common_names == rhs.ssl_certificate_common_names);
}
@ -112,6 +118,7 @@ void AuthenticationData::setPassword(const String & password_)
case AuthenticationType::NO_PASSWORD:
case AuthenticationType::LDAP:
case AuthenticationType::KERBEROS:
case AuthenticationType::SSL_CERTIFICATE:
throw Exception("Cannot specify password for authentication type " + toString(type), ErrorCodes::LOGICAL_ERROR);
case AuthenticationType::MAX:
@ -149,7 +156,7 @@ void AuthenticationData::setPasswordHashHex(const String & hash)
String AuthenticationData::getPasswordHashHex() const
{
if (type == AuthenticationType::LDAP || type == AuthenticationType::KERBEROS)
if (type == AuthenticationType::LDAP || type == AuthenticationType::KERBEROS || type == AuthenticationType::SSL_CERTIFICATE)
throw Exception("Cannot get password hex hash for authentication type " + toString(type), ErrorCodes::LOGICAL_ERROR);
String hex;
@ -194,6 +201,7 @@ void AuthenticationData::setPasswordHashBinary(const Digest & hash)
case AuthenticationType::NO_PASSWORD:
case AuthenticationType::LDAP:
case AuthenticationType::KERBEROS:
case AuthenticationType::SSL_CERTIFICATE:
throw Exception("Cannot specify password binary hash for authentication type " + toString(type), ErrorCodes::LOGICAL_ERROR);
case AuthenticationType::MAX:
@ -202,4 +210,12 @@ void AuthenticationData::setPasswordHashBinary(const Digest & hash)
throw Exception("setPasswordHashBinary(): authentication type " + toString(type) + " not supported", ErrorCodes::NOT_IMPLEMENTED);
}
void AuthenticationData::setSSLCertificateCommonNames(boost::container::flat_set<String> common_names_)
{
if (common_names_.empty())
throw Exception("The 'SSL CERTIFICATE' authentication type requires a non-empty list of common names.", ErrorCodes::BAD_ARGUMENTS);
ssl_certificate_common_names = std::move(common_names_);
}
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <base/types.h>
#include <boost/container/flat_set.hpp>
#include <vector>
namespace DB
@ -27,6 +28,10 @@ enum class AuthenticationType
/// Kerberos authentication performed through GSS-API negotiation loop.
KERBEROS,
/// Authentication is done in SSL by checking user certificate.
/// Certificates may only be trusted if 'strict' SSL mode is enabled.
SSL_CERTIFICATE,
MAX,
};
@ -79,6 +84,9 @@ public:
const String & getKerberosRealm() const { return kerberos_realm; }
void setKerberosRealm(const String & realm) { kerberos_realm = realm; }
const boost::container::flat_set<String> & getSSLCertificateCommonNames() const { return ssl_certificate_common_names; }
void setSSLCertificateCommonNames(boost::container::flat_set<String> common_names_);
friend bool operator ==(const AuthenticationData & lhs, const AuthenticationData & rhs);
friend bool operator !=(const AuthenticationData & lhs, const AuthenticationData & rhs) { return !(lhs == rhs); }
@ -97,6 +105,7 @@ private:
Digest password_hash;
String ldap_server_name;
String kerberos_realm;
boost::container::flat_set<String> ssl_certificate_common_names;
};
}

View File

@ -78,35 +78,4 @@ const RowPolicyFilterTypeInfo & RowPolicyFilterTypeInfo::get(RowPolicyFilterType
throw Exception("Unknown type: " + std::to_string(static_cast<size_t>(type_)), ErrorCodes::LOGICAL_ERROR);
}
String toString(RowPolicyKind kind)
{
return RowPolicyKindInfo::get(kind).raw_name;
}
const RowPolicyKindInfo & RowPolicyKindInfo::get(RowPolicyKind kind_)
{
static constexpr auto make_info = [](const char * raw_name_)
{
String init_name = raw_name_;
boost::to_lower(init_name);
return RowPolicyKindInfo{raw_name_, std::move(init_name)};
};
switch (kind_)
{
case RowPolicyKind::PERMISSIVE:
{
static const auto info = make_info("PERMISSIVE");
return info;
}
case RowPolicyKind::RESTRICTIVE:
{
static const auto info = make_info("RESTRICTIVE");
return info;
}
case RowPolicyKind::MAX: break;
}
throw Exception("Unknown kind: " + std::to_string(static_cast<size_t>(kind_)), ErrorCodes::LOGICAL_ERROR);
}
}

View File

@ -54,25 +54,4 @@ struct RowPolicyFilterTypeInfo
static const RowPolicyFilterTypeInfo & get(RowPolicyFilterType type);
};
/// Kinds of row policies. It affects how row policies are applied.
/// A row is only accessible if at least one of the permissive policies passes,
/// in addition to all the restrictive policies.
enum class RowPolicyKind
{
PERMISSIVE,
RESTRICTIVE,
MAX,
};
String toString(RowPolicyKind kind);
struct RowPolicyKindInfo
{
const char * const raw_name;
const String name; /// Lowercased with underscores, e.g. "permissive".
static const RowPolicyKindInfo & get(RowPolicyKind kind);
};
}

View File

@ -48,6 +48,20 @@ void AlwaysAllowCredentials::setUserName(const String & user_name_)
user_name = user_name_;
}
SSLCertificateCredentials::SSLCertificateCredentials(const String & user_name_, const String & common_name_)
: Credentials(user_name_)
, common_name(common_name_)
{
is_ready = true;
}
const String & SSLCertificateCredentials::getCommonName() const
{
if (!isReady())
throwNotReady();
return common_name;
}
BasicCredentials::BasicCredentials()
{
is_ready = true;

View File

@ -38,6 +38,17 @@ public:
void setUserName(const String & user_name_);
};
class SSLCertificateCredentials
: public Credentials
{
public:
explicit SSLCertificateCredentials(const String & user_name_, const String & common_name_);
const String & getCommonName() const;
private:
String common_name;
};
class BasicCredentials
: public Credentials
{

View File

@ -55,7 +55,7 @@ bool RowPolicy::equal(const IAccessEntity & other) const
return false;
const auto & other_policy = typeid_cast<const RowPolicy &>(other);
return (full_name == other_policy.full_name) && boost::range::equal(filters, other_policy.filters)
&& (kind == other_policy.kind) && (to_roles == other_policy.to_roles);
&& restrictive == other_policy.restrictive && (to_roles == other_policy.to_roles);
}
}

View File

@ -29,9 +29,17 @@ struct RowPolicy : public IAccessEntity
/// for user or available for modification.
std::array<String, static_cast<size_t>(RowPolicyFilterType::MAX)> filters;
/// Sets the kind of the policy, it affects how row policies are applied.
void setKind(RowPolicyKind kind_) { kind = kind_; }
RowPolicyKind getKind() const { return kind; }
/// Sets that the policy is permissive.
/// A row is only accessible if at least one of the permissive policies passes,
/// in addition to all the restrictive policies.
void setPermissive(bool permissive_ = true) { setRestrictive(!permissive_); }
bool isPermissive() const { return !isRestrictive(); }
/// Sets that the policy is restrictive.
/// A row is only accessible if at least one of the permissive policies passes,
/// in addition to all the restrictive policies.
void setRestrictive(bool restrictive_ = true) { restrictive = restrictive_; }
bool isRestrictive() const { return restrictive; }
bool equal(const IAccessEntity & other) const override;
std::shared_ptr<IAccessEntity> clone() const override { return cloneImpl<RowPolicy>(); }
@ -45,7 +53,7 @@ private:
void setName(const String &) override;
RowPolicyName full_name;
RowPolicyKind kind = RowPolicyKind::PERMISSIVE;
bool restrictive = false;
};
using RowPolicyPtr = std::shared_ptr<const RowPolicy>;

View File

@ -20,34 +20,21 @@ namespace
class FiltersMixer
{
public:
void add(const ASTPtr & filter, RowPolicyKind kind)
void add(const ASTPtr & filter, bool is_restrictive)
{
if (kind == RowPolicyKind::PERMISSIVE)
{
setPermissiveFiltersExist();
permissive_filters.push_back(filter);
}
if (is_restrictive)
restrictions.push_back(filter);
else
{
restrictive_filters.push_back(filter);
}
}
void setPermissiveFiltersExist()
{
permissive_filters_exist = true;
permissions.push_back(filter);
}
ASTPtr getResult() &&
{
if (permissive_filters_exist)
{
/// Process permissive filters.
restrictive_filters.push_back(makeASTForLogicalOr(std::move(permissive_filters)));
}
/// Process permissive filters.
restrictions.push_back(makeASTForLogicalOr(std::move(permissions)));
/// Process restrictive filters.
auto result = makeASTForLogicalAnd(std::move(restrictive_filters));
auto result = makeASTForLogicalAnd(std::move(restrictions));
bool value;
if (tryGetLiteralBool(result.get(), value) && value)
@ -57,9 +44,8 @@ namespace
}
private:
ASTs permissive_filters;
bool permissive_filters_exist = false;
ASTs restrictive_filters;
ASTs permissions;
ASTs restrictions;
};
}
@ -237,13 +223,8 @@ void RowPolicyCache::mixFiltersFor(EnabledRowPolicies & enabled)
key.filter_type = filter_type;
auto & mixer = mixers[key];
mixer.database_and_table_name = info.database_and_table_name;
if (policy.getKind() == RowPolicyKind::PERMISSIVE)
{
/// We call setPermissiveFiltersExist() even if the current user doesn't match to the current policy's TO clause.
mixer.mixer.setPermissiveFiltersExist();
}
if (match)
mixer.mixer.add(info.parsed_filters[filter_type_i], policy.getKind());
mixer.mixer.add(info.parsed_filters[filter_type_i], policy.isRestrictive());
}
}
}

View File

@ -62,13 +62,16 @@ namespace
bool has_ldap = config.has(user_config + ".ldap");
bool has_kerberos = config.has(user_config + ".kerberos");
size_t num_password_fields = has_no_password + has_password_plaintext + has_password_sha256_hex + has_password_double_sha1_hex + has_ldap + has_kerberos;
const auto certificates_config = user_config + ".ssl_certificates";
bool has_certificates = config.has(certificates_config);
size_t num_password_fields = has_no_password + has_password_plaintext + has_password_sha256_hex + has_password_double_sha1_hex + has_ldap + has_kerberos + has_certificates;
if (num_password_fields > 1)
throw Exception("More than one field of 'password', 'password_sha256_hex', 'password_double_sha1_hex', 'no_password', 'ldap', 'kerberos' are used to specify password for user " + user_name + ". Must be only one of them.",
throw Exception("More than one field of 'password', 'password_sha256_hex', 'password_double_sha1_hex', 'no_password', 'ldap', 'kerberos', 'certificates' are used to specify authentication info for user " + user_name + ". Must be only one of them.",
ErrorCodes::BAD_ARGUMENTS);
if (num_password_fields < 1)
throw Exception("Either 'password' or 'password_sha256_hex' or 'password_double_sha1_hex' or 'no_password' or 'ldap' or 'kerberos' must be specified for user " + user_name + ".", ErrorCodes::BAD_ARGUMENTS);
throw Exception("Either 'password' or 'password_sha256_hex' or 'password_double_sha1_hex' or 'no_password' or 'ldap' or 'kerberos' or 'certificates' must be specified for user " + user_name + ".", ErrorCodes::BAD_ARGUMENTS);
if (has_password_plaintext)
{
@ -105,6 +108,26 @@ namespace
user->auth_data = AuthenticationData{AuthenticationType::KERBEROS};
user->auth_data.setKerberosRealm(realm);
}
else if (has_certificates)
{
user->auth_data = AuthenticationData{AuthenticationType::SSL_CERTIFICATE};
/// Fill list of allowed certificates.
Poco::Util::AbstractConfiguration::Keys keys;
config.keys(certificates_config, keys);
boost::container::flat_set<String> common_names;
for (const String & key : keys)
{
if (key.starts_with("common_name"))
{
String value = config.getString(certificates_config + "." + key);
common_names.insert(std::move(value));
}
else
throw Exception("Unknown certificate pattern type: " + key, ErrorCodes::BAD_ARGUMENTS);
}
user->auth_data.setSSLCertificateCommonNames(std::move(common_names));
}
const auto profile_name_config = user_config + ".profile";
if (config.has(profile_name_config))

View File

@ -277,7 +277,7 @@ void registerDictionarySourceClickHouse(DictionarySourceFactory & factory)
{
/// We should set user info even for the case when the dictionary is loaded in-process (without TCP communication).
Session session(global_context, ClientInfo::Interface::LOCAL);
session.authenticate(configuration.user, configuration.password, {});
session.authenticate(configuration.user, configuration.password, Poco::Net::SocketAddress{});
context = session.makeQueryContext();
}
else

View File

@ -262,21 +262,20 @@ std::unique_ptr<WriteBufferFromFileBase> DiskS3::writeFile(const String & path,
LOG_TRACE(log, "{} to file by path: {}. S3 path: {}",
mode == WriteMode::Rewrite ? "Write" : "Append", backQuote(metadata_disk->getPath() + path), remote_fs_root_path + blob_name);
/// FIXME -- thread pool lead to obscure segfaults
/// ScheduleFunc schedule = [pool = &getThreadPoolWriter(), thread_group = CurrentThread::getGroup()](auto callback)
/// {
/// pool->scheduleOrThrow([callback = std::move(callback), thread_group]()
/// {
/// if (thread_group)
/// CurrentThread::attachTo(thread_group);
ScheduleFunc schedule = [pool = &getThreadPoolWriter(), thread_group = CurrentThread::getGroup()](auto callback)
{
pool->scheduleOrThrow([callback = std::move(callback), thread_group]()
{
if (thread_group)
CurrentThread::attachTo(thread_group);
/// SCOPE_EXIT_SAFE(
/// if (thread_group)
/// CurrentThread::detachQueryIfNotDetached();
/// );
/// callback();
/// });
/// };
SCOPE_EXIT_SAFE(
if (thread_group)
CurrentThread::detachQueryIfNotDetached();
);
callback();
});
};
auto s3_buffer = std::make_unique<WriteBufferFromS3>(
settings->client,

View File

@ -1,5 +1,7 @@
#include <Poco/Net/NetException.h>
#include <base/scope_guard.h>
#include <IO/ReadBufferFromPocoSocket.h>
#include <Common/Exception.h>
#include <Common/NetException.h>
@ -35,6 +37,12 @@ bool ReadBufferFromPocoSocket::nextImpl()
ssize_t bytes_read = 0;
Stopwatch watch;
SCOPE_EXIT({
// / NOTE: it is quite inaccurate on high loads since the thread could be replaced by another one
ProfileEvents::increment(ProfileEvents::NetworkReceiveElapsedMicroseconds, watch.elapsedMicroseconds());
ProfileEvents::increment(ProfileEvents::NetworkReceiveBytes, bytes_read);
});
/// Add more details to exceptions.
try
{
@ -66,10 +74,6 @@ bool ReadBufferFromPocoSocket::nextImpl()
if (bytes_read < 0)
throw NetException("Cannot read from socket (" + peer_address.toString() + ")", ErrorCodes::CANNOT_READ_FROM_SOCKET);
/// NOTE: it is quite inaccurate on high loads since the thread could be replaced by another one
ProfileEvents::increment(ProfileEvents::NetworkReceiveElapsedMicroseconds, watch.elapsedMicroseconds());
ProfileEvents::increment(ProfileEvents::NetworkReceiveBytes, bytes_read);
if (bytes_read)
working_buffer.resize(bytes_read);
else

View File

@ -1,5 +1,7 @@
#include <Poco/Net/NetException.h>
#include <base/scope_guard.h>
#include <IO/WriteBufferFromPocoSocket.h>
#include <Common/Exception.h>
@ -38,8 +40,13 @@ void WriteBufferFromPocoSocket::nextImpl()
return;
Stopwatch watch;
size_t bytes_written = 0;
SCOPE_EXIT({
ProfileEvents::increment(ProfileEvents::NetworkSendElapsedMicroseconds, watch.elapsedMicroseconds());
ProfileEvents::increment(ProfileEvents::NetworkSendBytes, bytes_written);
});
while (bytes_written < offset())
{
ssize_t res = 0;
@ -70,9 +77,6 @@ void WriteBufferFromPocoSocket::nextImpl()
bytes_written += res;
}
ProfileEvents::increment(ProfileEvents::NetworkSendElapsedMicroseconds, watch.elapsedMicroseconds());
ProfileEvents::increment(ProfileEvents::NetworkSendBytes, bytes_written);
}
WriteBufferFromPocoSocket::WriteBufferFromPocoSocket(Poco::Net::Socket & socket_, size_t buf_size)

View File

@ -29,8 +29,8 @@ namespace
else if (query.names->full_names.size() == 1)
policy.setFullName(query.names->full_names.front());
if (query.kind)
policy.setKind(*query.kind);
if (query.is_restrictive)
policy.setRestrictive(*query.is_restrictive);
for (const auto & [filter_type, filter] : query.filters)
policy.filters[static_cast<size_t>(filter_type)] = filter ? serializeAST(*filter) : String{};

View File

@ -189,7 +189,9 @@ namespace
query->names = std::make_shared<ASTRowPolicyNames>();
query->names->full_names.emplace_back(policy.getFullName());
query->attach = attach_mode;
query->kind = policy.getKind();
if (policy.isRestrictive())
query->is_restrictive = policy.isRestrictive();
for (auto type : collections::range(RowPolicyFilterType::MAX))
{

View File

@ -134,6 +134,12 @@ void ASTSystemQuery::formatImpl(const FormatSettings & settings, FormatState &,
<< (settings.hilite ? hilite_none : "");
};
auto print_identifier = [&](const String & identifier)
{
settings.ostr << " " << (settings.hilite ? hilite_identifier : "") << backQuoteIfNeed(identifier)
<< (settings.hilite ? hilite_none : "");
};
if (!cluster.empty())
formatOnCluster(settings);
@ -161,9 +167,19 @@ void ASTSystemQuery::formatImpl(const FormatSettings & settings, FormatState &,
|| type == Type::RESTORE_REPLICA
|| type == Type::SYNC_REPLICA
|| type == Type::FLUSH_DISTRIBUTED
|| type == Type::RELOAD_DICTIONARY)
|| type == Type::RELOAD_DICTIONARY
|| type == Type::RELOAD_MODEL
|| type == Type::RELOAD_FUNCTION
|| type == Type::RESTART_DISK)
{
print_database_table();
if (table)
print_database_table();
else if (!target_model.empty())
print_identifier(target_model);
else if (!target_function.empty())
print_identifier(target_function);
else if (!disk.empty())
print_identifier(disk);
}
else if (type == Type::DROP_REPLICA)
{

View File

@ -20,10 +20,10 @@ namespace
}
void formatAsKind(RowPolicyKind kind, const IAST::FormatSettings & settings)
void formatAsRestrictiveOrPermissive(bool is_restrictive, const IAST::FormatSettings & settings)
{
settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << " AS " << (settings.hilite ? IAST::hilite_none : "")
<< RowPolicyKindInfo::get(kind).name;
<< (is_restrictive ? "restrictive" : "permissive");
}
@ -156,10 +156,10 @@ void ASTCreateRowPolicyQuery::formatImpl(const FormatSettings & settings, Format
if (!new_short_name.empty())
formatRenameTo(new_short_name, settings);
formatForClauses(filters, alter, settings);
if (is_restrictive)
formatAsRestrictiveOrPermissive(*is_restrictive, settings);
if (kind)
formatAsKind(*kind, settings);
formatForClauses(filters, alter, settings);
if (roles && (!roles->empty() || alter))
formatToRoles(*roles, settings);

View File

@ -39,7 +39,7 @@ public:
std::shared_ptr<ASTRowPolicyNames> names;
String new_short_name;
std::optional<RowPolicyKind> kind;
std::optional<bool> is_restrictive;
std::vector<std::pair<RowPolicyFilterType, ASTPtr>> filters; /// `nullptr` means set to NONE.
std::shared_ptr<ASTRolesOrUsersSet> roles;

View File

@ -34,46 +34,58 @@ namespace
}
String auth_type_name = AuthenticationTypeInfo::get(auth_type).name;
String by_keyword = "BY";
std::optional<String> by_value;
String value_prefix;
std::optional<String> value;
const boost::container::flat_set<String> * values = nullptr;
if (
show_password ||
if (show_password ||
auth_type == AuthenticationType::LDAP ||
auth_type == AuthenticationType::KERBEROS
)
auth_type == AuthenticationType::KERBEROS ||
auth_type == AuthenticationType::SSL_CERTIFICATE)
{
switch (auth_type)
{
case AuthenticationType::PLAINTEXT_PASSWORD:
{
by_value = auth_data.getPassword();
value_prefix = "BY";
value = auth_data.getPassword();
break;
}
case AuthenticationType::SHA256_PASSWORD:
{
auth_type_name = "sha256_hash";
by_value = auth_data.getPasswordHashHex();
value_prefix = "BY";
value = auth_data.getPasswordHashHex();
break;
}
case AuthenticationType::DOUBLE_SHA1_PASSWORD:
{
auth_type_name = "double_sha1_hash";
by_value = auth_data.getPasswordHashHex();
value_prefix = "BY";
value = auth_data.getPasswordHashHex();
break;
}
case AuthenticationType::LDAP:
{
by_keyword = "SERVER";
by_value = auth_data.getLDAPServerName();
value_prefix = "SERVER";
value = auth_data.getLDAPServerName();
break;
}
case AuthenticationType::KERBEROS:
{
by_keyword = "REALM";
const auto & realm = auth_data.getKerberosRealm();
if (!realm.empty())
by_value = realm;
{
value_prefix = "REALM";
value = realm;
}
break;
}
case AuthenticationType::SSL_CERTIFICATE:
{
value_prefix = "CN";
values = &auth_data.getSSLCertificateCommonNames();
break;
}
@ -86,10 +98,26 @@ namespace
settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << " IDENTIFIED WITH " << auth_type_name
<< (settings.hilite ? IAST::hilite_none : "");
if (by_value)
if (!value_prefix.empty())
{
settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << " " << by_keyword << " "
<< (settings.hilite ? IAST::hilite_none : "") << quoteString(*by_value);
settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << " " << value_prefix
<< (settings.hilite ? IAST::hilite_none : "");
}
if (value)
{
settings.ostr << " " << quoteString(*value);
}
else if (values)
{
settings.ostr << " ";
bool need_comma = false;
for (const auto & item : *values)
{
if (std::exchange(need_comma, true))
settings.ostr << ", ";
settings.ostr << quoteString(item);
}
}
}

View File

@ -29,24 +29,24 @@ namespace
});
}
bool parseAsKind(IParserBase::Pos & pos, Expected & expected, RowPolicyKind & kind)
bool parseAsRestrictiveOrPermissive(IParserBase::Pos & pos, Expected & expected, bool & is_restrictive)
{
return IParserBase::wrapParseImpl(pos, [&]
{
if (!ParserKeyword{"AS"}.ignore(pos, expected))
return false;
for (auto current_kind : collections::range(RowPolicyKind::MAX))
if (ParserKeyword{"RESTRICTIVE"}.ignore(pos, expected))
{
const std::string_view & kind_name = RowPolicyKindInfo::get(current_kind).name;
if (ParserKeyword{kind_name.data()}.ignore(pos, expected))
{
kind = current_kind;
return true;
}
is_restrictive = true;
return true;
}
return false;
if (!ParserKeyword{"PERMISSIVE"}.ignore(pos, expected))
return false;
is_restrictive = false;
return true;
});
}
@ -243,7 +243,7 @@ bool ParserCreateRowPolicyQuery::parseImpl(Pos & pos, ASTPtr & node, Expected &
String cluster = std::exchange(names->cluster, "");
String new_short_name;
std::optional<RowPolicyKind> kind;
std::optional<bool> is_restrictive;
std::vector<std::pair<RowPolicyFilterType, ASTPtr>> filters;
while (true)
@ -251,12 +251,12 @@ bool ParserCreateRowPolicyQuery::parseImpl(Pos & pos, ASTPtr & node, Expected &
if (alter && (names->full_names.size() == 1) && new_short_name.empty() && parseRenameTo(pos, expected, new_short_name))
continue;
if (!kind)
if (!is_restrictive)
{
RowPolicyKind new_kind;
if (parseAsKind(pos, expected, new_kind))
bool new_is_restrictive;
if (parseAsRestrictiveOrPermissive(pos, expected, new_is_restrictive))
{
kind = new_kind;
is_restrictive = new_is_restrictive;
continue;
}
}
@ -291,7 +291,7 @@ bool ParserCreateRowPolicyQuery::parseImpl(Pos & pos, ASTPtr & node, Expected &
query->cluster = std::move(cluster);
query->names = std::move(names);
query->new_short_name = std::move(new_short_name);
query->kind = kind;
query->is_restrictive = is_restrictive;
query->filters = std::move(filters);
query->roles = std::move(roles);

View File

@ -52,6 +52,7 @@ namespace
bool expect_hash = false;
bool expect_ldap_server_name = false;
bool expect_kerberos_realm = false;
bool expect_common_names = false;
if (ParserKeyword{"WITH"}.ignore(pos, expected))
{
@ -65,6 +66,8 @@ namespace
expect_ldap_server_name = true;
else if (check_type == AuthenticationType::KERBEROS)
expect_kerberos_realm = true;
else if (check_type == AuthenticationType::SSL_CERTIFICATE)
expect_common_names = true;
else if (check_type != AuthenticationType::NO_PASSWORD)
expect_password = true;
@ -96,6 +99,7 @@ namespace
}
String value;
boost::container::flat_set<String> common_names;
if (expect_password || expect_hash)
{
ASTPtr ast;
@ -123,6 +127,18 @@ namespace
value = ast->as<const ASTLiteral &>().value.safeGet<String>();
}
}
else if (expect_common_names)
{
if (!ParserKeyword{"CN"}.ignore(pos, expected))
return false;
ASTPtr ast;
if (!ParserList{std::make_unique<ParserStringLiteral>(), std::make_unique<ParserToken>(TokenType::Comma), false}.parse(pos, ast, expected))
return false;
for (const auto & ast_child : ast->children)
common_names.insert(ast_child->as<const ASTLiteral &>().value.safeGet<String>());
}
auth_data = AuthenticationData{*type};
if (expect_password)
@ -133,6 +149,8 @@ namespace
auth_data.setLDAPServerName(value);
else if (expect_kerberos_realm)
auth_data.setKerberosRealm(value);
else if (expect_common_names)
auth_data.setSSLCertificateCommonNames(std::move(common_names));
return true;
});

View File

@ -64,6 +64,78 @@ static bool parseQueryWithOnClusterAndMaybeTable(std::shared_ptr<ASTSystemQuery>
return true;
}
enum class SystemQueryTargetType
{
Model,
Function,
Disk
};
static bool parseQueryWithOnClusterAndTarget(std::shared_ptr<ASTSystemQuery> & res, IParser::Pos & pos, Expected & expected, SystemQueryTargetType target_type)
{
/// Better form for user: SYSTEM <ACTION> target_name ON CLUSTER cluster
/// Query rewritten form + form while executing on cluster: SYSTEM <ACTION> ON CLUSTER cluster target_name
/// Need to support both
String cluster;
bool parsed_on_cluster = false;
if (ParserKeyword{"ON"}.ignore(pos, expected))
{
if (!ASTQueryWithOnCluster::parse(pos, cluster, expected))
return false;
parsed_on_cluster = true;
}
String target;
ASTPtr temporary_string_literal;
if (ParserStringLiteral{}.parse(pos, temporary_string_literal, expected))
{
target = temporary_string_literal->as<ASTLiteral &>().value.safeGet<String>();
}
else
{
ParserIdentifier identifier_parser;
ASTPtr identifier;
if (!identifier_parser.parse(pos, identifier, expected))
return false;
if (!tryGetIdentifierNameInto(identifier, target))
return false;
}
if (!parsed_on_cluster && ParserKeyword{"ON"}.ignore(pos, expected))
{
if (!ASTQueryWithOnCluster::parse(pos, cluster, expected))
return false;
}
res->cluster = cluster;
switch (target_type)
{
case SystemQueryTargetType::Model:
{
res->target_model = std::move(target);
break;
}
case SystemQueryTargetType::Function:
{
res->target_function = std::move(target);
break;
}
case SystemQueryTargetType::Disk:
{
res->disk = std::move(target);
break;
}
}
return true;
}
static bool parseQueryWithOnCluster(std::shared_ptr<ASTSystemQuery> & res, IParser::Pos & pos,
Expected & expected)
{
@ -112,50 +184,14 @@ bool ParserSystemQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected &
}
case Type::RELOAD_MODEL:
{
parseQueryWithOnCluster(res, pos, expected);
ASTPtr ast;
if (ParserStringLiteral{}.parse(pos, ast, expected))
{
res->target_model = ast->as<ASTLiteral &>().value.safeGet<String>();
}
else
{
ParserIdentifier model_parser;
ASTPtr model;
String target_model;
if (!model_parser.parse(pos, model, expected))
return false;
if (!tryGetIdentifierNameInto(model, res->target_model))
return false;
}
if (!parseQueryWithOnClusterAndTarget(res, pos, expected, SystemQueryTargetType::Model))
return false;
break;
}
case Type::RELOAD_FUNCTION:
{
parseQueryWithOnCluster(res, pos, expected);
ASTPtr ast;
if (ParserStringLiteral{}.parse(pos, ast, expected))
{
res->target_function = ast->as<ASTLiteral &>().value.safeGet<String>();
}
else
{
ParserIdentifier function_parser;
ASTPtr function;
String target_function;
if (!function_parser.parse(pos, function, expected))
return false;
if (!tryGetIdentifierNameInto(function, res->target_function))
return false;
}
if (!parseQueryWithOnClusterAndTarget(res, pos, expected, SystemQueryTargetType::Function))
return false;
break;
}
case Type::DROP_REPLICA:
@ -211,14 +247,8 @@ bool ParserSystemQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected &
case Type::RESTART_DISK:
{
parseQueryWithOnCluster(res, pos, expected);
ASTPtr ast;
if (ParserIdentifier{}.parse(pos, ast, expected))
res->disk = ast->as<ASTIdentifier &>().name();
else
if (!parseQueryWithOnClusterAndTarget(res, pos, expected, SystemQueryTargetType::Disk))
return false;
break;
}

View File

@ -13,6 +13,12 @@
#include <Poco/Net/HTTPStream.h>
#include <Poco/Net/NetException.h>
#if USE_SSL
#include <Poco/Net/SecureStreamSocketImpl.h>
#include <Poco/Net/SSLException.h>
#include <Poco/Net/X509Certificate.h>
#endif
namespace DB
{
HTTPServerRequest::HTTPServerRequest(ContextPtr context, HTTPServerResponse & response, Poco::Net::HTTPServerSession & session)
@ -69,6 +75,31 @@ bool HTTPServerRequest::checkPeerConnected() const
return true;
}
#if USE_SSL
bool HTTPServerRequest::havePeerCertificate() const
{
if (!secure)
return false;
const Poco::Net::SecureStreamSocketImpl * secure_socket = dynamic_cast<const Poco::Net::SecureStreamSocketImpl *>(socket);
if (!secure_socket)
return false;
return secure_socket->havePeerCertificate();
}
Poco::Net::X509Certificate HTTPServerRequest::peerCertificate() const
{
if (secure)
{
const Poco::Net::SecureStreamSocketImpl * secure_socket = dynamic_cast<const Poco::Net::SecureStreamSocketImpl *>(socket);
if (secure_socket)
return secure_socket->peerCertificate();
}
throw Poco::Net::SSLException("No certificate available");
}
#endif
void HTTPServerRequest::readRequest(ReadBuffer & in)
{
char ch;

View File

@ -3,9 +3,12 @@
#include <Interpreters/Context_fwd.h>
#include <IO/ReadBuffer.h>
#include <Server/HTTP/HTTPRequest.h>
#include <Common/config.h>
#include <Poco/Net/HTTPServerSession.h>
namespace Poco::Net { class X509Certificate; }
namespace DB
{
@ -38,6 +41,11 @@ public:
/// Returns the server's address.
const Poco::Net::SocketAddress & serverAddress() const { return server_address; }
#if USE_SSL
bool havePeerCertificate() const;
Poco::Net::X509Certificate peerCertificate() const;
#endif
private:
/// Limits for basic sanity checks when reading a header
enum Limits

View File

@ -44,6 +44,10 @@
#include <chrono>
#include <sstream>
#if USE_SSL
#include <Poco/Net/X509Certificate.h>
#endif
namespace DB
{
@ -98,6 +102,7 @@ namespace ErrorCodes
extern const int INVALID_SESSION_TIMEOUT;
extern const int HTTP_LENGTH_REQUIRED;
extern const int SUPPORT_IS_DISABLED;
}
namespace
@ -315,68 +320,93 @@ bool HTTPHandler::authenticateUser(
std::string password = request.get("X-ClickHouse-Key", "");
std::string quota_key = request.get("X-ClickHouse-Quota", "");
/// The header 'X-ClickHouse-SSL-Certificate-Auth: on' enables checking the common name
/// extracted from the SSL certificate used for this connection instead of checking password.
bool has_ssl_certificate_auth = (request.get("X-ClickHouse-SSL-Certificate-Auth", "") == "on");
bool has_auth_headers = !user.empty() || !password.empty() || !quota_key.empty() || has_ssl_certificate_auth;
/// User name and password can be passed using HTTP Basic auth or query parameters
/// (both methods are insecure).
bool has_http_credentials = request.hasCredentials();
bool has_credentials_in_query_params = params.has("user") || params.has("password") || params.has("quota_key");
std::string spnego_challenge;
std::string certificate_common_name;
if (user.empty() && password.empty() && quota_key.empty())
if (has_auth_headers)
{
/// User name and password can be passed using query parameters
/// or using HTTP Basic auth (both methods are insecure).
if (request.hasCredentials())
/// It is prohibited to mix different authorization schemes.
if (has_http_credentials)
throw Exception("Invalid authentication: it is not allowed to use SSL certificate authentication and Authorization HTTP header simultaneously", ErrorCodes::AUTHENTICATION_FAILED);
if (has_credentials_in_query_params)
throw Exception("Invalid authentication: it is not allowed to use SSL certificate authentication and authentication via parameters simultaneously simultaneously", ErrorCodes::AUTHENTICATION_FAILED);
if (has_ssl_certificate_auth)
{
/// It is prohibited to mix different authorization schemes.
if (params.has("user") || params.has("password"))
throw Exception("Invalid authentication: it is not allowed to use Authorization HTTP header and authentication via parameters simultaneously", ErrorCodes::AUTHENTICATION_FAILED);
#if USE_SSL
if (!password.empty())
throw Exception("Invalid authentication: it is not allowed to use SSL certificate authentication and authentication via password simultaneously", ErrorCodes::AUTHENTICATION_FAILED);
std::string scheme;
std::string auth_info;
request.getCredentials(scheme, auth_info);
if (request.havePeerCertificate())
certificate_common_name = request.peerCertificate().commonName();
if (Poco::icompare(scheme, "Basic") == 0)
{
HTTPBasicCredentials credentials(auth_info);
user = credentials.getUsername();
password = credentials.getPassword();
}
else if (Poco::icompare(scheme, "Negotiate") == 0)
{
spnego_challenge = auth_info;
if (certificate_common_name.empty())
throw Exception("Invalid authentication: SSL certificate authentication requires nonempty certificate's Common Name", ErrorCodes::AUTHENTICATION_FAILED);
#else
throw Exception(
"SSL certificate authentication disabled because ClickHouse was built without SSL library",
ErrorCodes::SUPPORT_IS_DISABLED);
#endif
}
}
else if (has_http_credentials)
{
/// It is prohibited to mix different authorization schemes.
if (has_credentials_in_query_params)
throw Exception("Invalid authentication: it is not allowed to use Authorization HTTP header and authentication via parameters simultaneously", ErrorCodes::AUTHENTICATION_FAILED);
if (spnego_challenge.empty())
throw Exception("Invalid authentication: SPNEGO challenge is empty", ErrorCodes::AUTHENTICATION_FAILED);
}
else
{
throw Exception("Invalid authentication: '" + scheme + "' HTTP Authorization scheme is not supported", ErrorCodes::AUTHENTICATION_FAILED);
}
std::string scheme;
std::string auth_info;
request.getCredentials(scheme, auth_info);
if (Poco::icompare(scheme, "Basic") == 0)
{
HTTPBasicCredentials credentials(auth_info);
user = credentials.getUsername();
password = credentials.getPassword();
}
else if (Poco::icompare(scheme, "Negotiate") == 0)
{
spnego_challenge = auth_info;
if (spnego_challenge.empty())
throw Exception("Invalid authentication: SPNEGO challenge is empty", ErrorCodes::AUTHENTICATION_FAILED);
}
else
{
user = params.get("user", "default");
password = params.get("password", "");
throw Exception("Invalid authentication: '" + scheme + "' HTTP Authorization scheme is not supported", ErrorCodes::AUTHENTICATION_FAILED);
}
quota_key = params.get("quota_key", "");
}
else
{
/// It is prohibited to mix different authorization schemes.
if (request.hasCredentials() || params.has("user") || params.has("password") || params.has("quota_key"))
throw Exception("Invalid authentication: it is not allowed to use X-ClickHouse HTTP headers and other authentication methods simultaneously", ErrorCodes::AUTHENTICATION_FAILED);
/// If the user name is not set we assume it's the 'default' user.
user = params.get("user", "default");
password = params.get("password", "");
quota_key = params.get("quota_key", "");
}
if (spnego_challenge.empty()) // I.e., now using user name and password strings ("Basic").
if (!certificate_common_name.empty())
{
if (!request_credentials)
request_credentials = std::make_unique<BasicCredentials>();
request_credentials = std::make_unique<SSLCertificateCredentials>(user, certificate_common_name);
auto * basic_credentials = dynamic_cast<BasicCredentials *>(request_credentials.get());
if (!basic_credentials)
throw Exception("Invalid authentication: unexpected 'Basic' HTTP Authorization scheme", ErrorCodes::AUTHENTICATION_FAILED);
basic_credentials->setUserName(user);
basic_credentials->setPassword(password);
auto * certificate_credentials = dynamic_cast<SSLCertificateCredentials *>(request_credentials.get());
if (!certificate_credentials)
throw Exception("Invalid authentication: expected SSL certificate authorization scheme", ErrorCodes::AUTHENTICATION_FAILED);
}
else
else if (!spnego_challenge.empty())
{
if (!request_credentials)
request_credentials = server.context()->makeGSSAcceptorContext();
@ -403,6 +433,18 @@ bool HTTPHandler::authenticateUser(
return false;
}
}
else // I.e., now using user name and password strings ("Basic").
{
if (!request_credentials)
request_credentials = std::make_unique<BasicCredentials>();
auto * basic_credentials = dynamic_cast<BasicCredentials *>(request_credentials.get());
if (!basic_credentials)
throw Exception("Invalid authentication: expected 'Basic' HTTP Authorization scheme", ErrorCodes::AUTHENTICATION_FAILED);
basic_credentials->setUserName(user);
basic_credentials->setPassword(password);
}
/// Set client info. It will be used for quota accounting parameters in 'setUser' method.
ClientInfo & client_info = session->getClientInfo();

View File

@ -10,7 +10,6 @@
#include <DataTypes/DataTypesNumber.h>
#include <DataTypes/DataTypeUUID.h>
#include <DataTypes/DataTypeNullable.h>
#include <DataTypes/DataTypeEnum.h>
#include <DataTypes/DataTypeArray.h>
#include <Interpreters/Context.h>
#include <Parsers/Access/ASTRolesOrUsersSet.h>
@ -20,26 +19,6 @@
namespace DB
{
namespace
{
const std::vector<std::pair<String, Int8>> & getRowPolicyKindEnumValues()
{
static const std::vector<std::pair<String, Int8>> values = []
{
std::vector<std::pair<String, Int8>> res;
for (auto kind : collections::range(RowPolicyKind::MAX))
{
const std::string_view & kind_name = RowPolicyKindInfo::get(kind).name;
res.emplace_back(kind_name, static_cast<Int8>(kind));
}
return res;
}();
return values;
}
}
NamesAndTypesList StorageSystemRowPolicies::getNamesAndTypes()
{
NamesAndTypesList names_and_types{
@ -58,7 +37,7 @@ NamesAndTypesList StorageSystemRowPolicies::getNamesAndTypes()
}
NamesAndTypesList extra_names_and_types{
{"kind", std::make_shared<DataTypeEnum8>(getRowPolicyKindEnumValues())},
{"is_restrictive", std::make_shared<DataTypeUInt8>()},
{"apply_to_all", std::make_shared<DataTypeUInt8>()},
{"apply_to_list", std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>())},
{"apply_to_except", std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>())}
@ -92,7 +71,7 @@ void StorageSystemRowPolicies::fillData(MutableColumns & res_columns, ContextPtr
column_filter_null_map[filter_type_i] = &assert_cast<ColumnNullable &>(*res_columns[column_index++]).getNullMapData();
}
auto & column_kind = assert_cast<ColumnInt8 &>(*res_columns[column_index++]).getData();
auto & column_is_restrictive = assert_cast<ColumnUInt8 &>(*res_columns[column_index++]).getData();
auto & column_apply_to_all = assert_cast<ColumnUInt8 &>(*res_columns[column_index++]).getData();
auto & column_apply_to_list = assert_cast<ColumnString &>(assert_cast<ColumnArray &>(*res_columns[column_index]).getData());
auto & column_apply_to_list_offsets = assert_cast<ColumnArray &>(*res_columns[column_index++]).getOffsets();
@ -104,7 +83,7 @@ void StorageSystemRowPolicies::fillData(MutableColumns & res_columns, ContextPtr
const UUID & id,
const String & storage_name,
const std::array<String, static_cast<size_t>(RowPolicyFilterType::MAX)> & filters,
RowPolicyKind kind,
bool is_restrictive,
const RolesOrUsersSet & apply_to)
{
column_name.insertData(name.data(), name.length());
@ -130,7 +109,7 @@ void StorageSystemRowPolicies::fillData(MutableColumns & res_columns, ContextPtr
}
}
column_kind.push_back(static_cast<Int8>(kind));
column_is_restrictive.push_back(is_restrictive);
auto apply_to_ast = apply_to.toASTWithNames(access_control);
column_apply_to_all.push_back(apply_to_ast->all);
@ -153,7 +132,7 @@ void StorageSystemRowPolicies::fillData(MutableColumns & res_columns, ContextPtr
if (!storage)
continue;
add_row(policy->getName(), policy->getFullName(), id, storage->getStorageName(), policy->filters, policy->getKind(), policy->to_roles);
add_row(policy->getName(), policy->getFullName(), id, storage->getStorageName(), policy->filters, policy->isRestrictive(), policy->to_roles);
}
}
}

View File

@ -102,17 +102,27 @@ void StorageSystemUsers::fillData(MutableColumns & res_columns, ContextPtr conte
column_storage.insertData(storage_name.data(), storage_name.length());
column_auth_type.push_back(static_cast<Int8>(auth_data.getType()));
if (
auth_data.getType() == AuthenticationType::LDAP ||
auth_data.getType() == AuthenticationType::KERBEROS
)
if (auth_data.getType() == AuthenticationType::LDAP ||
auth_data.getType() == AuthenticationType::KERBEROS ||
auth_data.getType() == AuthenticationType::SSL_CERTIFICATE)
{
Poco::JSON::Object auth_params_json;
if (auth_data.getType() == AuthenticationType::LDAP)
{
auth_params_json.set("server", auth_data.getLDAPServerName());
}
else if (auth_data.getType() == AuthenticationType::KERBEROS)
{
auth_params_json.set("realm", auth_data.getKerberosRealm());
}
else if (auth_data.getType() == AuthenticationType::SSL_CERTIFICATE)
{
Poco::JSON::Array::Ptr arr = new Poco::JSON::Array();
for (const auto & common_name : auth_data.getSSLCertificateCommonNames())
arr->add(common_name);
auth_params_json.set("common_names", arr);
}
std::ostringstream oss; // STYLE_CHECK_ALLOW_STD_STRING_STREAM
oss.exceptions(std::ios::failbit);

View File

@ -120,11 +120,23 @@ def _get_status_style(status):
return style
def _get_html_url(url):
def _get_html_url_name(url):
if isinstance(url, str):
return '<a href="{url}">{name}</a>'.format(url=url, name=os.path.basename(url).replace('%2B', '+').replace('%20', ' '))
return os.path.basename(url).replace('%2B', '+').replace('%20', ' ')
if isinstance(url, tuple):
return '<a href="{url}">{name}</a>'.format(url=url[0], name=url[1].replace('%2B', '+').replace('%20', ' '))
return url[1].replace('%2B', '+').replace('%20', ' ')
return None
def _get_html_url(url):
href = None
name = None
if isinstance(url, str):
href, name = url, _get_html_url_name(url)
if isinstance(url, tuple):
href, name = url[0], _get_html_url_name(url)
if href and name:
return '<a href="{href}">{name}</a>'.format(href=href, name=_get_html_url_name(url))
return ''
@ -193,9 +205,7 @@ def create_test_html_report(header, test_result, raw_log_url, task_url, branch_u
else:
test_part = ""
additional_html_urls = ""
for url in additional_urls:
additional_html_urls += ' ' + _get_html_url(url)
additional_html_urls = ' '.join([_get_html_url(url) for url in sorted(additional_urls, key=_get_html_url_name)])
result = HTML_BASE_TEST_TEMPLATE.format(
title=_format_header(header, branch_name),
@ -307,7 +317,7 @@ def create_build_html_report(header, build_results, build_logs_urls, artifact_ur
link_separator = "<br/>"
if artifact_urls:
for artifact_url in artifact_urls:
links += LINK_TEMPLATE.format(text=os.path.basename(artifact_url.replace('%2B', '+').replace('%20', ' ')), url=artifact_url)
links += LINK_TEMPLATE.format(text=_get_html_url_name(artifact_url), url=artifact_url)
links += link_separator
if links:
links = links[:-len(link_separator)]

View File

@ -42,7 +42,7 @@ def test_create():
assert instance.query(
"SHOW CREATE USER u2") == "CREATE USER u2 IDENTIFIED WITH sha256_password HOST LOCAL DEFAULT ROLE rx\n"
assert instance.query(
"SHOW CREATE ROW POLICY p ON mydb.mytable") == "CREATE ROW POLICY p ON mydb.mytable FOR SELECT USING a < 1000 AS permissive TO u1, u2\n"
"SHOW CREATE ROW POLICY p ON mydb.mytable") == "CREATE ROW POLICY p ON mydb.mytable FOR SELECT USING a < 1000 TO u1, u2\n"
assert instance.query(
"SHOW CREATE QUOTA q") == "CREATE QUOTA q FOR INTERVAL 1 hour MAX queries = 100 TO ALL EXCEPT rx\n"
assert instance.query("SHOW GRANTS FOR u1") == ""

View File

@ -256,21 +256,21 @@ def test_reload_users_xml_by_timer():
def test_introspection():
policies = [
["another ON mydb.filtered_table1", "another", "mydb", "filtered_table1",
"6068883a-0e9d-f802-7e22-0144f8e66d3c", "users.xml", "1", "permissive", 0, "['another']", "[]"],
"6068883a-0e9d-f802-7e22-0144f8e66d3c", "users.xml", "1", 0, 0, "['another']", "[]"],
["another ON mydb.filtered_table2", "another", "mydb", "filtered_table2",
"c019e957-c60b-d54e-cc52-7c90dac5fb01", "users.xml", "1", "permissive", 0, "['another']", "[]"],
"c019e957-c60b-d54e-cc52-7c90dac5fb01", "users.xml", "1", 0, 0, "['another']", "[]"],
["another ON mydb.filtered_table3", "another", "mydb", "filtered_table3",
"4cb080d0-44e8-dbef-6026-346655143628", "users.xml", "1", "permissive", 0, "['another']", "[]"],
"4cb080d0-44e8-dbef-6026-346655143628", "users.xml", "1", 0, 0, "['another']", "[]"],
["another ON mydb.local", "another", "mydb", "local", "5b23c389-7e18-06bf-a6bc-dd1afbbc0a97", "users.xml",
"a = 1", "permissive", 0, "['another']", "[]"],
"a = 1", 0, 0, "['another']", "[]"],
["default ON mydb.filtered_table1", "default", "mydb", "filtered_table1",
"9e8a8f62-4965-2b5e-8599-57c7b99b3549", "users.xml", "a = 1", "permissive", 0, "['default']", "[]"],
"9e8a8f62-4965-2b5e-8599-57c7b99b3549", "users.xml", "a = 1", 0, 0, "['default']", "[]"],
["default ON mydb.filtered_table2", "default", "mydb", "filtered_table2",
"cffae79d-b9bf-a2ef-b798-019c18470b25", "users.xml", "a + b < 1 or c - d > 5", "permissive", 0, "['default']", "[]"],
"cffae79d-b9bf-a2ef-b798-019c18470b25", "users.xml", "a + b < 1 or c - d > 5", 0, 0, "['default']", "[]"],
["default ON mydb.filtered_table3", "default", "mydb", "filtered_table3",
"12fc5cef-e3da-3940-ec79-d8be3911f42b", "users.xml", "c = 1", "permissive", 0, "['default']", "[]"],
"12fc5cef-e3da-3940-ec79-d8be3911f42b", "users.xml", "c = 1", 0, 0, "['default']", "[]"],
["default ON mydb.local", "default", "mydb", "local", "cdacaeb5-1d97-f99d-2bb0-4574f290629c", "users.xml", "1",
"permissive", 0, "['default']", "[]"]
0, 0, "['default']", "[]"]
]
assert node.query("SELECT * from system.row_policies ORDER BY short_name, database, table") == TSV(policies)
@ -292,49 +292,49 @@ def test_dcl_introspection():
"default ON mydb.local"])
assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table1") == "CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 AS permissive TO default\n"
"SHOW CREATE POLICY default ON mydb.filtered_table1") == "CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 TO default\n"
assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table2") == "CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) AS permissive TO default\n"
"SHOW CREATE POLICY default ON mydb.filtered_table2") == "CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) TO default\n"
assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table3") == "CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 AS permissive TO default\n"
"SHOW CREATE POLICY default ON mydb.filtered_table3") == "CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 TO default\n"
assert node.query(
"SHOW CREATE POLICY default ON mydb.local") == "CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 AS permissive TO default\n"
"SHOW CREATE POLICY default ON mydb.local") == "CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 TO default\n"
assert node.query("SHOW CREATE POLICY default") == TSV(
["CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 AS permissive TO default",
"CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) AS permissive TO default",
"CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 AS permissive TO default",
"CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 AS permissive TO default"])
["CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 TO default",
"CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) TO default",
"CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 TO default",
"CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 TO default"])
assert node.query("SHOW CREATE POLICIES ON mydb.filtered_table1") == TSV(
["CREATE ROW POLICY another ON mydb.filtered_table1 FOR SELECT USING 1 AS permissive TO another",
"CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 AS permissive TO default"])
["CREATE ROW POLICY another ON mydb.filtered_table1 FOR SELECT USING 1 TO another",
"CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 TO default"])
assert node.query("SHOW CREATE POLICIES ON mydb.*") == TSV(
["CREATE ROW POLICY another ON mydb.filtered_table1 FOR SELECT USING 1 AS permissive TO another",
"CREATE ROW POLICY another ON mydb.filtered_table2 FOR SELECT USING 1 AS permissive TO another",
"CREATE ROW POLICY another ON mydb.filtered_table3 FOR SELECT USING 1 AS permissive TO another",
"CREATE ROW POLICY another ON mydb.local FOR SELECT USING a = 1 AS permissive TO another",
"CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 AS permissive TO default",
"CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) AS permissive TO default",
"CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 AS permissive TO default",
"CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 AS permissive TO default"])
["CREATE ROW POLICY another ON mydb.filtered_table1 FOR SELECT USING 1 TO another",
"CREATE ROW POLICY another ON mydb.filtered_table2 FOR SELECT USING 1 TO another",
"CREATE ROW POLICY another ON mydb.filtered_table3 FOR SELECT USING 1 TO another",
"CREATE ROW POLICY another ON mydb.local FOR SELECT USING a = 1 TO another",
"CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 TO default",
"CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) TO default",
"CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 TO default",
"CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 TO default"])
assert node.query("SHOW CREATE POLICIES") == TSV(
["CREATE ROW POLICY another ON mydb.filtered_table1 FOR SELECT USING 1 AS permissive TO another",
"CREATE ROW POLICY another ON mydb.filtered_table2 FOR SELECT USING 1 AS permissive TO another",
"CREATE ROW POLICY another ON mydb.filtered_table3 FOR SELECT USING 1 AS permissive TO another",
"CREATE ROW POLICY another ON mydb.local FOR SELECT USING a = 1 AS permissive TO another",
"CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 AS permissive TO default",
"CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) AS permissive TO default",
"CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 AS permissive TO default",
"CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 AS permissive TO default"])
["CREATE ROW POLICY another ON mydb.filtered_table1 FOR SELECT USING 1 TO another",
"CREATE ROW POLICY another ON mydb.filtered_table2 FOR SELECT USING 1 TO another",
"CREATE ROW POLICY another ON mydb.filtered_table3 FOR SELECT USING 1 TO another",
"CREATE ROW POLICY another ON mydb.local FOR SELECT USING a = 1 TO another",
"CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 TO default",
"CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) TO default",
"CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 TO default",
"CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 TO default"])
expected_access = "CREATE ROW POLICY another ON mydb.filtered_table1 FOR SELECT USING 1 AS permissive TO another\n" \
"CREATE ROW POLICY another ON mydb.filtered_table2 FOR SELECT USING 1 AS permissive TO another\n" \
"CREATE ROW POLICY another ON mydb.filtered_table3 FOR SELECT USING 1 AS permissive TO another\n" \
"CREATE ROW POLICY another ON mydb.local FOR SELECT USING a = 1 AS permissive TO another\n" \
"CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 AS permissive TO default\n" \
"CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) AS permissive TO default\n" \
"CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 AS permissive TO default\n" \
"CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 AS permissive TO default\n"
expected_access = "CREATE ROW POLICY another ON mydb.filtered_table1 FOR SELECT USING 1 TO another\n" \
"CREATE ROW POLICY another ON mydb.filtered_table2 FOR SELECT USING 1 TO another\n" \
"CREATE ROW POLICY another ON mydb.filtered_table3 FOR SELECT USING 1 TO another\n" \
"CREATE ROW POLICY another ON mydb.local FOR SELECT USING a = 1 TO another\n" \
"CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING a = 1 TO default\n" \
"CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING ((a + b) < 1) OR ((c - d) > 5) TO default\n" \
"CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 1 TO default\n" \
"CREATE ROW POLICY default ON mydb.local FOR SELECT USING 1 TO default\n"
assert expected_access in node.query("SHOW ACCESS")
copy_policy_xml('all_rows.xml')
@ -342,22 +342,22 @@ def test_dcl_introspection():
["another ON mydb.filtered_table1", "another ON mydb.filtered_table2", "another ON mydb.filtered_table3",
"default ON mydb.filtered_table1", "default ON mydb.filtered_table2", "default ON mydb.filtered_table3"])
assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table1") == "CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING 1 AS permissive TO default\n"
"SHOW CREATE POLICY default ON mydb.filtered_table1") == "CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING 1 TO default\n"
assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table2") == "CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING 1 AS permissive TO default\n"
"SHOW CREATE POLICY default ON mydb.filtered_table2") == "CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING 1 TO default\n"
assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table3") == "CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING 1 AS permissive TO default\n"
"SHOW CREATE POLICY default ON mydb.filtered_table3") == "CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING 1 TO default\n"
copy_policy_xml('no_rows.xml')
assert node.query("SHOW POLICIES") == TSV(
["another ON mydb.filtered_table1", "another ON mydb.filtered_table2", "another ON mydb.filtered_table3",
"default ON mydb.filtered_table1", "default ON mydb.filtered_table2", "default ON mydb.filtered_table3"])
assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table1") == "CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING NULL AS permissive TO default\n"
"SHOW CREATE POLICY default ON mydb.filtered_table1") == "CREATE ROW POLICY default ON mydb.filtered_table1 FOR SELECT USING NULL TO default\n"
assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table2") == "CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING NULL AS permissive TO default\n"
"SHOW CREATE POLICY default ON mydb.filtered_table2") == "CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING NULL TO default\n"
assert node.query(
"SHOW CREATE POLICY default ON mydb.filtered_table3") == "CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING NULL AS permissive TO default\n"
"SHOW CREATE POLICY default ON mydb.filtered_table3") == "CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING NULL TO default\n"
copy_policy_xml('no_filters.xml')
assert node.query("SHOW POLICIES") == ""
@ -382,7 +382,7 @@ def test_dcl_management():
assert node.query("SELECT * FROM mydb.filtered_table1") == TSV([[1, 0]])
assert node.query("SHOW POLICIES ON mydb.filtered_table1") == "pB\n"
assert node.query(
"SHOW CREATE POLICY pB ON mydb.filtered_table1") == "CREATE ROW POLICY pB ON mydb.filtered_table1 FOR SELECT USING a > b AS permissive TO default\n"
"SHOW CREATE POLICY pB ON mydb.filtered_table1") == "CREATE ROW POLICY pB ON mydb.filtered_table1 FOR SELECT USING a > b TO default\n"
node.query("DROP POLICY pB ON mydb.filtered_table1")
assert node.query("SELECT * FROM mydb.filtered_table1") == TSV([[0, 0], [0, 1], [1, 0], [1, 1]])
@ -435,23 +435,6 @@ def test_grant_create_row_policy():
node.query("DROP USER X")
def test_some_users_without_policies():
copy_policy_xml('no_filters.xml')
assert node.query("SHOW POLICIES") == ""
node.query("CREATE USER X, Y")
node.query("GRANT SELECT ON mydb.filtered_table1 TO X, Y")
node.query("CREATE POLICY pA ON mydb.filtered_table1 FOR SELECT USING a<b AS permissive TO X")
assert node.query("SELECT * FROM mydb.filtered_table1", user='X') == TSV([[0, 1]])
assert node.query("SELECT * FROM mydb.filtered_table1", user='Y') == ""
node.query("ALTER POLICY pA ON mydb.filtered_table1 AS restrictive")
assert node.query("SELECT * FROM mydb.filtered_table1", user='X') == TSV([[0, 1]])
assert node.query("SELECT * FROM mydb.filtered_table1", user='Y') == TSV([[0, 0], [0, 1], [1, 0], [1, 1]])
node.query("DROP USER X, Y")
def test_users_xml_is_readonly():
assert re.search("storage is readonly", node.query_and_get_error("DROP POLICY default ON mydb.filtered_table1"))
@ -465,10 +448,10 @@ def test_tags_with_db_and_table_names():
assert node.query("SELECT * FROM mydb.`.filtered_table4`") == TSV([[1, 1]])
assert node.query("SHOW CREATE POLICIES default") == TSV(
["CREATE ROW POLICY default ON mydb.`.filtered_table4` FOR SELECT USING c = 2 AS permissive TO default",
"CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING c > (d + 5) AS permissive TO default",
"CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 0 AS permissive TO default",
"CREATE ROW POLICY default ON mydb.table FOR SELECT USING a = 0 AS permissive TO default"])
["CREATE ROW POLICY default ON mydb.`.filtered_table4` FOR SELECT USING c = 2 TO default",
"CREATE ROW POLICY default ON mydb.filtered_table2 FOR SELECT USING c > (d + 5) TO default",
"CREATE ROW POLICY default ON mydb.filtered_table3 FOR SELECT USING c = 0 TO default",
"CREATE ROW POLICY default ON mydb.table FOR SELECT USING a = 0 TO default"])
def test_miscellaneous_engines():

View File

@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFhTCCA22gAwIBAgIUVRNcr0jCH3vSTxg8QYQH6CCtyF4wDQYJKoZIhvcNAQEL
BQAwUjELMAkGA1UEBhMCUlUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDELMAkGA1UEAwwCY2EwHhcNMjIwMjE4
MDk0MzA2WhcNMzIwMjE2MDk0MzA2WjBSMQswCQYDVQQGEwJSVTETMBEGA1UECAwK
U29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQsw
CQYDVQQDDAJjYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALwojNvu
fXQYQ4tucqNOEDHf2sNgxwxqY6QdtJ+zNfVjsK4I3Vqo8TtzxfDYGolkYem/bYJM
xQar9ehUm9ok/0kJgIo8vDXxxDJtvjz5Fd5oFWJLMxojLE9NSa0A4m18jGfbFNsF
XoU0njiInyzNaU9d4bMpaweseCZdt9Y4LR93FkuhSU/v18lWQPob8SSIij059IZP
sEUxpDOTxclAmG/Knd/6v3ecVFiQgexZM0gCtf7kcw41mxsAaP/mOexodIZDR70Y
LYjL7R2ZGhpClfQc8SO5NSpfEqsfreDX7XoaCTsy7/rqr3Nfiby6sc//awG0Ww/f
FRf2+2BU2xEwOVa3i5wU5raYY6eqFLK9q9c2IWPSqYzAmvhK2pqWQ/iaCU/Q89ow
SbKudJTLK8Y6v9LW4Q8ZLZF+CzS5cI+QEfIYqTLFdInH1BLoxx7cymEv07CDkcTo
2WtV8GdMph2P3U/9NoXQDonjCSj0lQUjgUdcrBPaIIVbIn6/5vfw8LQa8PoGDhIx
AYQkqPR+LHxCqIMzdqKZ+OXD/HPhiigpxLhF7mVRLvvoyrOZVJbcu1qmgCcQw0IE
fWzvWne+9cYC9lgt8+/k6d6B1uhYsIwwhgoj0dffFjc0sF6zfceGK+H1K2JCE0aY
zT1HlvSoZdA7lEs5xbGJnkBHqlOvQ63ynXCzAgMBAAGjUzBRMB0GA1UdDgQWBBTn
AtgFU20JF7kTZCKlY7/hi0kYRzAfBgNVHSMEGDAWgBTnAtgFU20JF7kTZCKlY7/h
i0kYRzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQCpiWgJ1XUw
a8Bdeznsa57oy+5mqQZWpRVkzTQRHEGV850OGh7WQ6u9kVAHefaHH9hsVxyggton
6/MDsu4KL5jqKmJaIAepPIOw6DTc2zs044I7W/rxRp+w1hL2TS+EahMrSPwdzCcl
NNAM0dXocGylf6qwwMqiYAR1K3UIrlyq4QTr1oEPIqJBkDg1JDYrt4T2DroPjW20
5hlCQ/tft5ddGL0EFEaKWwAcPFm7jAwJiz2eUqmT6PcmaZ24qPn5RXVkaBAkrSga
1WgM8r3LGu2EKhdiDc5hRJKjS8RZyLvZNNzlL3+N42nGmGZkND5bV6u82OD+qn17
LRZOt0Cr70HqszSYk/67ijjaa4n/fuuAqorV+yYB8accRXtoi00nxykT+H+yI1rD
swvcrfDvhUgY5zmunWyQUYh0q/2Hj75GbLup3Cd0B4MrBwqyCqcEugM4OSf6aRMr
e/vjeggTVPN08xE1LUkugalx0B0aoO6qFahJ2CmkAcYLLlS2N+F7TMuPavc0kVxD
I3qA5G9zvNCliSLX2+kM+LzslI8+pP/A98bvh6nW4HtZkI0jq1ks7XR0GeOhCI8E
0l/YuElxxgKhN4INKhhMoDKqPib4z8gbmkenR2CenQCpfLMIrhTXZgtw+gvEgpIE
/QK97G8XPqga6zn471wrYJnuyJli+sP7aw==
-----END CERTIFICATE-----

View File

@ -0,0 +1 @@
05F10C67567FE30795D77AF2540F6AC8D4CF2461

View File

@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQC8KIzb7n10GEOL
bnKjThAx39rDYMcMamOkHbSfszX1Y7CuCN1aqPE7c8Xw2BqJZGHpv22CTMUGq/Xo
VJvaJP9JCYCKPLw18cQybb48+RXeaBViSzMaIyxPTUmtAOJtfIxn2xTbBV6FNJ44
iJ8szWlPXeGzKWsHrHgmXbfWOC0fdxZLoUlP79fJVkD6G/EkiIo9OfSGT7BFMaQz
k8XJQJhvyp3f+r93nFRYkIHsWTNIArX+5HMONZsbAGj/5jnsaHSGQ0e9GC2Iy+0d
mRoaQpX0HPEjuTUqXxKrH63g1+16Ggk7Mu/66q9zX4m8urHP/2sBtFsP3xUX9vtg
VNsRMDlWt4ucFOa2mGOnqhSyvavXNiFj0qmMwJr4StqalkP4mglP0PPaMEmyrnSU
yyvGOr/S1uEPGS2Rfgs0uXCPkBHyGKkyxXSJx9QS6Mce3MphL9Owg5HE6NlrVfBn
TKYdj91P/TaF0A6J4wko9JUFI4FHXKwT2iCFWyJ+v+b38PC0GvD6Bg4SMQGEJKj0
fix8QqiDM3aimfjlw/xz4YooKcS4Re5lUS776MqzmVSW3LtapoAnEMNCBH1s71p3
vvXGAvZYLfPv5OnegdboWLCMMIYKI9HX3xY3NLBes33Hhivh9StiQhNGmM09R5b0
qGXQO5RLOcWxiZ5AR6pTr0Ot8p1wswIDAQABAoICAQCO/c4Wccb7TFlAhD4wpumd
zX5GDq0WXV+94CldWGdARnOFvwzhkhRJ1zDtWH3KPfQ/HJBPfqIY8OQfnPUYMhej
3MnHxGJQKJyuqkHxumYJMFZX7cg3K9XHqne8NzjcddOKNa9Cx3DOkG9RjVpSRQSs
IS+d5XMGUOa6WWyVKvn3uJvD/B1n12DJDHiy2jtHRVCxOPMAg1z1KMWdwMaFrEZs
ZrHV/ow1jSN4btGd2SgkqJLA08IwYUKvoX8qQj9wzu0G/+hr5wzrsfZQEQMKQ+IL
s1b6jAzAV6IrVBbjEZXSviiXyZ0gteuCJW/acpMg+/3JPNQbWrCAFt1wluwowto/
JAFIvlh29hfE5c+HEMpQNa0tdj7jepBn/0YEbgwpayMikKiLZXEpgheWCGypAQWp
Hm+N0Ym7HSGe82obxi8EjKRnNwFUtotWzUBKeo9aFwPZHLFlspljd+5ynDvKqXnk
txYZj6K3TtMs30HAG6fqxSPyiZ5W+5yF7nt6qLODs6m4Os+lrk1GnoqC0/uLMzIU
CRJKulrJOK4/Z2tPn9IAhcREbS4oROUeNqqo0Cfs3ssvkV7JTHF4IsKhCmElMmGa
bevOI+pvdjfECShy0Jnbtni6ece/II4/edfUp9kWN45xZLpzDjfqCVD66JS9g6ZU
i/EVll+d5zaI2TzzwZgHUQKCAQEA3d8siwXbq7x0cAB013+tvkvGMJ2EuS1TWdLk
a2P6CAnlZMWvv2cPSd2WpimHjqKxrbn6VE79mOc2l9Y1NOUUWWZATrhN7V8xMapQ
0YiYCHeaMERUAUKdzCgRN2/mRbZCBzpPBbWbb6NtKfRFJsD9zAe2JBwDVh9hvAL8
YVBoczrEfj1ILnmtPhAJVI6s6rDsA4MgKjLs0Tt7Cc7rQxqNSpHEvwv1yLQmjp0N
L5b1TEt7fqVJ9dirykJquBYEKf55Z1qZhQzmnbu9OPnzeqGDakl5F/UsXDB5Bokp
ilcV+nFbh175Q+gTEhaSacGW8gzRw6j18PuciBjeWVEM5hhxOwKCAQEA2RnRMjv9
46jQarJTFbIHg1SqrR87GSLnt6672M5TX9frzxMCuVDjKgdecstvLjm6X+/cPQKT
Q3javJnJXT4cx//1J7RLO6ZBVSCZf3//XntdHdFVJf5ySQtK+MJyfxjpzP6KBPfb
WPrva8p29ejbBdtsOT0M6gY5tPfadU2XEaf+BoyX9NUmu1U46Iqi+eCOjR+GVvhP
pJzGgLeOsaRVCfc9I7XPoVu3AEx5Kt55yRYm4fyGPsAd+mRDbIXMXdL0k8CfWWDr
8TT5rqKI+gFPFQCwToBW3DwHIGY+3RmoXFfQ0IJaKwOk4AB7m6HC3mv1crtjTFSM
9p74oQzNX7UG6QKCAQBEs2cygRTdH5SaXbnQRKvC4emzggLn5/4IMUIjcqioNpA+
XOwngzz7rU6JkxBzfTMxTQYTdwYVg3qnF2AQSeK8L+o3teADYVd1PnyZ9QbGkGpB
CddNMJh17+4s0UxnR6E4Zbi0VuCTd/JEbGvBLT8pHzYqBjaOQ1dbBT2q0GAXVhoj
0Mv6ABlBv2t0MF2gqjnaeI7MIkqsGxPlHJpChAU+EtbuJUDs7cOGo2DC3KaGAlVy
CLJXGslO7rPm3oJZkn97HlWtGiqKquhTrSnUThDIJ4oEfhlHTocbG/ut53tZuiIS
T7k1arYFAtJBRv17Y7bMNBQ7k12L0s9+rpck5GqjAoIBAQCVBPSkj6tZbpII+viu
5rHjguVYyhwtx9jYK1eDnTR7kGGrlPgErjIPslkxYNSjHTsCCUnakv70jGtQlBs1
JqJo4hesNkSB4D/uJ99VNk3a08D566uP1dUqsFa44/flp/ssG/gvKtbkf/KBwcrg
RwK4RYJG09IefUF1J8BLToQIuZBTfIP9qaXZZskWTbtK28ndsqrq3a0FaBuVVOnc
o9k/avcLoQuxTZwS12tAcs+TqOHtswGO5x5stg/V2Q2LxXbeSJTYq/+oZN2R8r0l
JmrbFsruR4fXylh189jouWjoYdrSlPdBmVG99HbkQCfbtq0XIOsrBMpxqnMtUPVT
4ZWpAoIBAQCrao4XHpRM3KsfPqdkg0vqFDBA+LzKlWu1fl8w5TGpFK8H1tv5kHNv
h0XmeU5cXwiweri3KjQz7h+qVBHZeAvyrEoxJQdImax+5OUy7lysDs+SL02gLZb3
Z7g+u4Buwx+cv4O7hwUEDDk/5X3NBFk7/iwztKUtM+Fl8jt9K3K24s87xXp9YevI
UEawden9jVcuXQjEUrwz8cjoz/y25vK5pQ6k82PVImkMZK99/PmgmGyOl7hdRA3F
ff0Kb8pRGmV/cWRKzHaC8QchW8jdU2EGxMkrFl1DvoVKLbyDf1glRncKP9iozHAR
+s184IJCUvyMxH83uKKAiBGaDRC+Lbm7
-----END PRIVATE KEY-----

View File

@ -0,0 +1,30 @@
-----BEGIN CERTIFICATE-----
MIIFMDCCAxgCFAXxDGdWf+MHldd68lQPasjUzyRfMA0GCSqGSIb3DQEBCwUAMFIx
CzAJBgNVBAYTAlJVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl
cm5ldCBXaWRnaXRzIFB0eSBMdGQxCzAJBgNVBAMMAmNhMB4XDTIyMDIxODA5NDMw
OVoXDTMyMDIxNjA5NDMwOVowVzELMAkGA1UEBhMCUlUxEzARBgNVBAgMClNvbWUt
U3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEQMA4GA1UE
AwwHY2xpZW50MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMBU0fao
RrITeF4kpN81p7qirX/Gc56+Cux6u7RF1O6WU9v+V5jLw8chQZ87z4QSrFiT1ZnT
pwWYPwJ+pDk6AWEoiKuOaceOh0bjZCuxADHs+qQrye5D8GXvyFvWE2cT1pD5JNEZ
DSl2YHqNs4uTGRP9BP817iRDcuvdxpanaWxfXGfehJRMiEVgKDs+RUpoW4aVNivI
InrUWc4RXXkzaJKqhpCU3jAJBV4jSD5ZnA8PUfcoAj6z6T3I6phuDfRP5ldA3br8
yg0hCB7Y5QrO5lRAgEoIuNnC+U6/AIwWPI36Rjiwg3EUwI/BIiL4AWjzkjSdr0mn
zyHPRk4pcn01T0GTpQi6tfZZpumDD3LkPuEy9svMpJ8ntqDnAsIJVjbg1S60hHes
yYHoQw1HxU0vrncxwcQkVaPLx0uGlioaLlvu83AVnWXbylZXsV/pLy6dE3H51GBF
DX3Zj6nkuJitk8/hNp440/Lve7SaKFPo5NdH+8ACWGdFdz3zxgPuhBDoxEeqj4c1
FQA1ABXx2akW3lQ5VxTAg5AYORvVhJTozosr+Kn3MlRdZjl94tnVByD8MGLLE0C4
L/qXR/IlbkOCz5LHapdC5j62ZEBwiElmMO/tMGl4ORV9tdTBrRZ9DMmKek2E8Qwz
y770PGkhp1cTzZt6UfZEympowmfjtiZfHIq1AgMBAAEwDQYJKoZIhvcNAQELBQAD
ggIBAHwRpqnpcD3EW588GSDZhZrVf3nS9M06ljQGtDUqNSI4XJp1cVT1sMaa4LjM
cWgHtayFw+jbDLwioXHjMlV+8tERH+0x+qsADG349caDYT/OF13v/jyuboUZ9AqE
KpfOQH7jCLU7rEbEl6kvT3F3xaHJg8mE7msyRFfguB2JrqZkKIj4HANxJUJo4PwB
5bq9nE3AVNAgUeQEwfu0r5SjroNpcHfm7xWqMK2mDMCsy/DvI7n97Q7vZajcTT0x
UXfgx+3CLEvLMpa2myE5OIMOeLzfZwxrxyNH7BdZsROnkGv1cX+9HZpYcue/UDxp
P2OApbTuZKaTJOyMADc17s0seE0DTAHnHAWrJwVhf8wYKKtEs+i+Sw5LNSkh5fgS
hTzGF93yClDYzWEqMSKhKPeimtpz4ZBNuGf471KbpVbUKJJvJmOxqoZ5S0kpFILL
YMALf652uf5or5d0cDNvcJTwvMi6evchIV17d/jH+MxyJQs9VCkMpJxFbMrXb3YB
b57K3Z25P6w3Qfj4zuKQFANari7Gs6qSiaUBiEhEdTQlGspkq+FLndtX818sbMk5
LAK6JaUH0ywV2jn5XSW0irQLDXqb6Q0bSyw6pdpDjk0o4UW67JCE4kGagRDnfSqL
ZODvO/dEtVLyAsjmOx8MkqLyseI7VESVd8eiJAyL0sifh+/E
-----END CERTIFICATE-----

View File

@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
zjy/DZmOU/a/EiR7MCGg+jS1x9GBxOE=
-----END PRIVATE KEY-----

View File

@ -0,0 +1,27 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIEnDCCAoQCAQAwVzELMAkGA1UEBhMCUlUxEzARBgNVBAgMClNvbWUtU3RhdGUx
ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEQMA4GA1UEAwwHY2xp
ZW50MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMBU0faoRrITeF4k
pN81p7qirX/Gc56+Cux6u7RF1O6WU9v+V5jLw8chQZ87z4QSrFiT1ZnTpwWYPwJ+
pDk6AWEoiKuOaceOh0bjZCuxADHs+qQrye5D8GXvyFvWE2cT1pD5JNEZDSl2YHqN
s4uTGRP9BP817iRDcuvdxpanaWxfXGfehJRMiEVgKDs+RUpoW4aVNivIInrUWc4R
XXkzaJKqhpCU3jAJBV4jSD5ZnA8PUfcoAj6z6T3I6phuDfRP5ldA3br8yg0hCB7Y
5QrO5lRAgEoIuNnC+U6/AIwWPI36Rjiwg3EUwI/BIiL4AWjzkjSdr0mnzyHPRk4p
cn01T0GTpQi6tfZZpumDD3LkPuEy9svMpJ8ntqDnAsIJVjbg1S60hHesyYHoQw1H
xU0vrncxwcQkVaPLx0uGlioaLlvu83AVnWXbylZXsV/pLy6dE3H51GBFDX3Zj6nk
uJitk8/hNp440/Lve7SaKFPo5NdH+8ACWGdFdz3zxgPuhBDoxEeqj4c1FQA1ABXx
2akW3lQ5VxTAg5AYORvVhJTozosr+Kn3MlRdZjl94tnVByD8MGLLE0C4L/qXR/Il
bkOCz5LHapdC5j62ZEBwiElmMO/tMGl4ORV9tdTBrRZ9DMmKek2E8Qwzy770PGkh
p1cTzZt6UfZEympowmfjtiZfHIq1AgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAgEA
fGx/D6rNeaVO/vSUGX5q1iJKd8Gnw+/8NRgbuvCDuDOSy8LyqnLmVntj8q9FHpJM
SRH3LnylMVFZdybso2ZbhR1UDReGvHCtKICG3LLP1uWwy5nS3mkGBHFm9COyFP21
kWOit1+106gEhg2f/NXh31HFmh+myepLjPEj5KxvnQhQfaQESsDYDZAs6/qT1mqp
A7GixOXh7hIFBJ97cU7fKby0Wtv7GqKAYQkaf26ImoGijtMPIlzvwJboJWmOYzIH
zrOHqspFkJD8YvYOwLIKdahViqXU7POL9uRn0vFyaXVcyXRq83Pz+bPSW9AFYsYG
ukSZiJs1yCINZI/Mk1vlfaZWYPIbBkJZ0Ny0vw112dIEilWAkVdsmJyV95aBddQI
Md64CYWZbV5P7/0QOX+v2ZQpWVnaV0m07K6VVuTL3bw6BQ9fcj7vaql6wl8jl/9l
nEotaZiY1f1pUUko3XzXpZEFB1lGBHupuS/Plz8pfFefN/7sOZoWn1VhD9I1A8uh
b2mg6hyQ7pe2NrHOTY1+L1xxxKKHt01kvDhws09qxRXtNsLrL8tl94i1ndLjHIwD
/VRnVU04E/VoTKaEXuETLZwOZu8pLwdiejrWEAmtsbmmcKq/Bk42wa+Wrmge2Chs
V8EOAtq91AjUcQeh7s2fV6yWweMGm1J6pdkNWckCsUs=
-----END CERTIFICATE REQUEST-----

View File

@ -0,0 +1,30 @@
-----BEGIN CERTIFICATE-----
MIIFMDCCAxgCFAXxDGdWf+MHldd68lQPasjUzyRgMA0GCSqGSIb3DQEBCwUAMFIx
CzAJBgNVBAYTAlJVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl
cm5ldCBXaWRnaXRzIFB0eSBMdGQxCzAJBgNVBAMMAmNhMB4XDTIyMDIxODA5NDMw
OVoXDTMyMDIxNjA5NDMwOVowVzELMAkGA1UEBhMCUlUxEzARBgNVBAgMClNvbWUt
U3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEQMA4GA1UE
AwwHY2xpZW50MjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOGIanwq
rZCqMT+ePwRkiQnD0gyVt5+kwkb8X+fdBJRF0kr70YfzMpKdZP4l4W6C0Jv/ysIH
usrI5pQxcFAIe/7DLW0JPkMLKgXsOtPNZPIkc7WYkq3cbzB0ZTsK8O3IYhwn0dAY
O49T//YqM3TLTFsG89B6uCEg7dQiP9hh6boic8M/WyAseOkJNfw+wYcTWhl1toKc
dLbo8ehESUtVhCOPVT602zBUYFkleqKPeHJ/gzl3/mTnqfeUBljGI2aXwOl7r6rI
D/or7wew2HZ81dTGDqB+yqUhBIVNseJPHOuKbke2E2qWVzAkRnX4b2ehsSaSknpC
KGWyLibaQyR0/Gt8Duu1XIsZKeFjCw27yogSTQ6xTUhLDF1anQyoJX9btSQZsTbD
3vtHbD1O07KSfiG0Z1p8LaR10RAFA7f3HLwwy6c9ExpGu5ED+co8aO5Xp5wysg8X
fYZYx4CaY3moQPJPDS6eOpUXd/6h27Fm34h9VdSj2p6j9JYsmTeEgb0x+JjAQyRS
+Koj/tbSbBqjbvO+FUaldRlHCHYCQTnjsSNBf7SxqE9lfgFitcgiHKSdD7QIfwNB
EK1o7L8OugC/SQtHGe3ngUGuNmHI9w6ItGuVqoJYP3Hwa6ClGmYlTRLoAj8NkBib
toxwGIspTlTzmmLXpqeZTPaA2K5eiq8O5DKvAgMBAAEwDQYJKoZIhvcNAQELBQAD
ggIBALp4L1aky2jfgk18tney56sUL2Us2aHqyOz9LlowWFdNMtCKo0WKpZ1qXGfQ
92QE+zc/MEdmv3V/H1MmSr7trTq1u7E5vVVI9Lq2lNbRLDQLi1+qd9E7Kdl6Oxw/
Ecc8oxIbg86p83HhzPfJG64m3x6S6m2c4sNrHRAO/gxxJex6ZSFfQwYJZFlcvvBX
CH70RBtBG/ggasVtwqBuuIRNJ2gAtiWG2RtyGlOjPiAg7nUQiYlXLHVOjvrKDvrI
KTjzRdEUMqKtIrNUBHSbWZlxKZ2Ddavshg/0T0reAN/u5KTDxiGaQxlVEA7xfm+j
etqjzTz7LnKuRsA+Z8UUYaV6mKYfKObDoUs/12IomRCUTQi1K8MP3fGmmk+4Xiyu
+t15EqWJzhjuT2RjCAL47X6ksdOtonX9t29l6ykCvYpK1mlzG+EhqDyMIn62TNfx
OFjWwhIFgyEUWtwkihIKtv3ZVtrJVO/j+HCUfq+6IpjYHdlpdb4OaHgBtpokOtM8
PmTHJbP2bxmNIMAU1WTfV+e/JkdTKHJclC5DTGF48yRgdKSOTq0G1eJYh4DhlEIM
vOw2rXeWR6VSkvA5vF7HANEptl1tkT3dsKR4BXkSIO16ldWBEHMM4UeXx85GGM0k
TRON4FWBMi6PXX6mrmPXcUW7AyKG2JL9gNlxRgWHVK7xmZyp
-----END CERTIFICATE-----

View File

@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
X0ueOR40kfa077G7jNfb03qOPUR1mFw=
-----END PRIVATE KEY-----

View File

@ -0,0 +1,27 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIEnDCCAoQCAQAwVzELMAkGA1UEBhMCUlUxEzARBgNVBAgMClNvbWUtU3RhdGUx
ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEQMA4GA1UEAwwHY2xp
ZW50MjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOGIanwqrZCqMT+e
PwRkiQnD0gyVt5+kwkb8X+fdBJRF0kr70YfzMpKdZP4l4W6C0Jv/ysIHusrI5pQx
cFAIe/7DLW0JPkMLKgXsOtPNZPIkc7WYkq3cbzB0ZTsK8O3IYhwn0dAYO49T//Yq
M3TLTFsG89B6uCEg7dQiP9hh6boic8M/WyAseOkJNfw+wYcTWhl1toKcdLbo8ehE
SUtVhCOPVT602zBUYFkleqKPeHJ/gzl3/mTnqfeUBljGI2aXwOl7r6rID/or7wew
2HZ81dTGDqB+yqUhBIVNseJPHOuKbke2E2qWVzAkRnX4b2ehsSaSknpCKGWyLiba
QyR0/Gt8Duu1XIsZKeFjCw27yogSTQ6xTUhLDF1anQyoJX9btSQZsTbD3vtHbD1O
07KSfiG0Z1p8LaR10RAFA7f3HLwwy6c9ExpGu5ED+co8aO5Xp5wysg8XfYZYx4Ca
Y3moQPJPDS6eOpUXd/6h27Fm34h9VdSj2p6j9JYsmTeEgb0x+JjAQyRS+Koj/tbS
bBqjbvO+FUaldRlHCHYCQTnjsSNBf7SxqE9lfgFitcgiHKSdD7QIfwNBEK1o7L8O
ugC/SQtHGe3ngUGuNmHI9w6ItGuVqoJYP3Hwa6ClGmYlTRLoAj8NkBibtoxwGIsp
TlTzmmLXpqeZTPaA2K5eiq8O5DKvAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAgEA
3DJlf7AkZklzzswgm487f+y2bB7IYr55JwENASDxQEOdVcdgLC3IWu3hLiFwdqac
0Sw2OHZuETwJiIX3fD+qUT6TgbsP21W7wEQ4jfKg/bsXFMbrvw/ILkOW2JLTH4Cc
9ylCN+46dQ9heATkiF/Co+uASz9IoSDdtoycA3BuKGBZI8VGa56QmJOOsMM5NgxT
RTh2r23tV4E8AGYj3HC+b1rzK1RTlsj/m5nM9Jv0/NqoV1cprS1ONr8CBhN0ttuA
WLrG+DUZTMJYFabqTptlgejQFhiFp5HT5A+eXgZ8uEUX1I3q5jq1BEWtLdmJNZ45
QViSJOokH/+1kfRSWiAH7pdBz4URLBcsDhAag4J7kV38t7fgdaIizY8R2Ss82iEP
xqa4A0PA065wB44zng/VrPrHoH1YnGRugXEnrqgcipC0FxUl3oQjvwOSR/E7yFU0
GIr1MpRcyrd0z4p16783qnMpE1Aa0msED2SBKIK13WcNY+CtDF/wO47ZNywl1hBo
VkM+ohPpmonaVXNGdpdoZpeGjkBUbqkn+so4aYkX/WuZ6vY2vwdV0prD1vdAFfD2
AeJx5ypu5aeKn6nK0eMy6W/VEJx6RLCiYVOCIcssgy31rmk4iLQJP2StYVK2mZKp
5aSR4eTv1/XlMujq+ZqcuUqA1id9wP7908Xr0DzdNdA=
-----END CERTIFICATE REQUEST-----

View File

@ -0,0 +1,30 @@
-----BEGIN CERTIFICATE-----
MIIFMDCCAxgCFAXxDGdWf+MHldd68lQPasjUzyRhMA0GCSqGSIb3DQEBCwUAMFIx
CzAJBgNVBAYTAlJVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl
cm5ldCBXaWRnaXRzIFB0eSBMdGQxCzAJBgNVBAMMAmNhMB4XDTIyMDIxODA5NDMw
OVoXDTMyMDIxNjA5NDMwOVowVzELMAkGA1UEBhMCUlUxEzARBgNVBAgMClNvbWUt
U3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEQMA4GA1UE
AwwHY2xpZW50MzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAN8Bt8gv
50J66lQ+l/NUW+lqW4DesmSLv1BnjDd5SSA8tfczt999/l1epAGeEN/Pl4dAxXP/
cxpx+J+xF6SKNxQ0RP+PHQMiDzCUgBq4OKs09kDQ/uvycUZlQuWPtR610TWjZR5r
VrNSwJQp3VGDdNyEbKj/yd6Yi5NC1iLuqPC20fw5/9BVTm1P2wWX7nv1AWs235s2
yAG7pLNcgPiTfSmXyyT31YBjb9Onun7gv7exI/3K9mS+aWq6ci1xAXtykVCs551T
OQmDAUxda041YghEThO4MrZa6uSZqVwnoUcXTla+8biLYb3+9CnIjM5whAOTR+9r
jpsuuXEUOsrX9Mgb1HTS+ksmrA+Eka7MdVi60Hoon09uNvcTM8CSKNgnTzcPCM6t
J4NHDiimJM5WA/eY8i3NNCTa1HUGEeIK51UOdjIFKsvzG0TCI2FM7jQLJK5S38tI
deZ98iQbguVGhoCvRotLEAwW1M2rSOu7bxAZU4QJ93IuUfkLn2BipOuyuR55Z/6F
z5Jij/1lK2/pKWhntUHTIpG+bBHDF++0LN0aB29uIwYRkoz9JUgnNz4FDVbLvJ+z
5Ywr61t8AujZdfMZDpRYlzfWPGej8pm7/Eux5jgx/3jcLtqfqkfZLSuFjBKfkUU1
eGsC80RupMJKIeppv541W6nQJlmJYKv7DCvrAgMBAAEwDQYJKoZIhvcNAQELBQAD
ggIBAD+YMVntBdeq7xJEL7xU4QEHzUGhDWodGMJfmswcxe7gf5Nztcq5YIug+akL
ewg0wzgCA5YGz00J92sKDF16RmYyPfkxmrCYdNGwISjNJyEEcPEVkdAzwILjv2Lq
0shFlSsf+Zp/M4XhHeirmzz/jJ9KHlzEYoCz1WOn+UGF12KgV2oQOamJSWOMCoMh
81oy90V5IlCBqnYfZCYj7cbYLBd5jZMZ+7lsVnxttzPTg1gIoP6vrLT32Ubnzx9N
IoAeiUg7az/fbnuOkJtu0cjz9aSdpjm2h2giyVAFJ8DkQ9C92tdr9DWZKn7rDO16
TMdv0q8NFjRGhqdmqWUG6o2cUmQsJ/ZiIcHx5X1b7j7PYSS+ae9zi1tcpHAN6kCw
WHguIf5I8MIZxE741ZMBokFSIqd6Bh1EP/TUx1+g2a/nH3ZaNd4/KKADxfUU2Y58
UwdKeX9YpcRz+NNO+1h3NoE1a/i0dhwiBf4OzBiV0WpAjQHT95IlQxTxfHFp42IH
GrbqIS3qK5DKlNFkBBk1beKxBGKmTH+Pw6fhjkuPYQzjmGo4xluivfeT8SiBT2iO
uIGLd+sitIooom0KEjHuHS9cdZ5XEPIUDAFhmIt7Y5K8J2fs+xtYzhibg3n0Q6qh
xTx7GzhTA1HSUE/467af5J3CSfpGAjZQZo/t2/A6tCumzk9F
-----END CERTIFICATE-----

View File

@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
I68TOg71OfCKgfeixNgcOvQoN+xngA==
-----END PRIVATE KEY-----

View File

@ -0,0 +1,27 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIEnDCCAoQCAQAwVzELMAkGA1UEBhMCUlUxEzARBgNVBAgMClNvbWUtU3RhdGUx
ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEQMA4GA1UEAwwHY2xp
ZW50MzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAN8Bt8gv50J66lQ+
l/NUW+lqW4DesmSLv1BnjDd5SSA8tfczt999/l1epAGeEN/Pl4dAxXP/cxpx+J+x
F6SKNxQ0RP+PHQMiDzCUgBq4OKs09kDQ/uvycUZlQuWPtR610TWjZR5rVrNSwJQp
3VGDdNyEbKj/yd6Yi5NC1iLuqPC20fw5/9BVTm1P2wWX7nv1AWs235s2yAG7pLNc
gPiTfSmXyyT31YBjb9Onun7gv7exI/3K9mS+aWq6ci1xAXtykVCs551TOQmDAUxd
a041YghEThO4MrZa6uSZqVwnoUcXTla+8biLYb3+9CnIjM5whAOTR+9rjpsuuXEU
OsrX9Mgb1HTS+ksmrA+Eka7MdVi60Hoon09uNvcTM8CSKNgnTzcPCM6tJ4NHDiim
JM5WA/eY8i3NNCTa1HUGEeIK51UOdjIFKsvzG0TCI2FM7jQLJK5S38tIdeZ98iQb
guVGhoCvRotLEAwW1M2rSOu7bxAZU4QJ93IuUfkLn2BipOuyuR55Z/6Fz5Jij/1l
K2/pKWhntUHTIpG+bBHDF++0LN0aB29uIwYRkoz9JUgnNz4FDVbLvJ+z5Ywr61t8
AujZdfMZDpRYlzfWPGej8pm7/Eux5jgx/3jcLtqfqkfZLSuFjBKfkUU1eGsC80Ru
pMJKIeppv541W6nQJlmJYKv7DCvrAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAgEA
Rggrols8hXGEcWeIEGn66kY9IVTzaTUf3oMfEbdf/2Q1QzHzmqp53yamHl5ioMgX
o5UBVxthgh1VOxkvCxIzlKDJprzVFkfwwc7h9c0HGt3No/ERobHDT6YRaGukAL5g
muIGBUseyBAOIfyqc5kbCRWfPrAOttAH4gd8XMBgO8XdfHAvyXBC8Ha55O6oriX9
IAKL5+3nVJkBle+62OmROnstbcdKyK4UtOeki/6ptYVE0d9I+NfKjuk3eKtICW8Q
Pn3IEcNEZoFG2UQ19ENWwYEZyMZJt0aunqnm7L4RYiZT5w4meeendzXSKLKR6+Ye
ULt1sDRskgKoNRzmeCVzci05BG48jv/E7Az6aV/qhGiU2qIAPMdVXncWUhR3fj+E
CL/uLifOvfC6SnKw/7qQmgjUvEe4Duvi670a5QuImpm/mAIN22cXPc+QquSdR5xy
loz/o3JJQZemPAOM0CMIHZ+cGESxH30QCBNn5HfcOf5fRZVCss4Hl6JxHR2G4yN3
RKEIUXR03qgSK91WHl3WvqwXgmIAiUuvPjo2i7kSuaUUHilZiXK1ngIqYfUTB5SQ
O8pG0fx3fbhVDA3RQfXeJE6FA2AyLvqOcsseRzvcQjQm4MU7p+RVaY17rI6/EkS8
ac3E7BPwnXqSAkPSEgoiezv/Z0Hkmrcu6fIsUuf4ETU=
-----END CERTIFICATE REQUEST-----

View File

@ -0,0 +1,23 @@
#!/bin/bash
# 1. Generate CA's private key and self-signed certificate
openssl req -newkey rsa:4096 -x509 -days 3650 -nodes -batch -keyout ca-key.pem -out ca-cert.pem -subj "/C=RU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=ca"
# 2. Generate server's private key and certificate signing request (CSR)
openssl req -newkey rsa:4096 -nodes -batch -keyout server-key.pem -out server-req.pem -subj "/C=RU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=server"
# 3. Use CA's private key to sign server's CSR and get back the signed certificate
openssl x509 -req -days 3650 -in server-req.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -extfile server-ext.cnf -out server-cert.pem
# 4. Generate client's private key and certificate signing request (CSR)
openssl req -newkey rsa:4096 -nodes -batch -keyout client1-key.pem -out client1-req.pem -subj "/C=RU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=client1"
openssl req -newkey rsa:4096 -nodes -batch -keyout client2-key.pem -out client2-req.pem -subj "/C=RU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=client2"
openssl req -newkey rsa:4096 -nodes -batch -keyout client3-key.pem -out client3-req.pem -subj "/C=RU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=client3"
# 5. Use CA's private key to sign client's CSR and get back the signed certificate
openssl x509 -req -days 3650 -in client1-req.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out client1-cert.pem
openssl x509 -req -days 3650 -in client2-req.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out client2-cert.pem
openssl x509 -req -days 3650 -in client3-req.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out client3-cert.pem
# 6. Generate one more self-signed certificate and private key for using as wrong certificate (because it's not signed by CA)
openssl req -newkey rsa:4096 -x509 -days 3650 -nodes -batch -keyout wrong-key.pem -out wrong-cert.pem -subj "/C=RU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=client"

View File

@ -0,0 +1,31 @@
-----BEGIN CERTIFICATE-----
MIIFSTCCAzGgAwIBAgIUBfEMZ1Z/4weV13ryVA9qyNTPJF4wDQYJKoZIhvcNAQEL
BQAwUjELMAkGA1UEBhMCUlUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDELMAkGA1UEAwwCY2EwHhcNMjIwMjE4
MDk0MzA2WhcNMzIwMjE2MDk0MzA2WjBWMQswCQYDVQQGEwJSVTETMBEGA1UECAwK
U29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ8w
DQYDVQQDDAZzZXJ2ZXIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC8
jV8igQGgCvu/7BJDI5VQl43VGAFjH2Na/E9P4E5uwkSlJVED1WKvIlxRWhOaQOfC
587nZVhQtHpdbCvBdKrHml4SVbTchs5SN2kZsHeqaQzcGnejnczE0SYo4xNyniSv
GiQ1M8G3fiZNflEIPM/+Ob2oI3YnVWFGy0a5rQcHZWS45KuGILMP0aRHyzyh/31c
K3i2xA7A3V2jBNuD4kHG8TLgfDeoCecTI0iU/LJnDOolX5XdpyeoJ6YyYOGg3F9e
bRmbNlJN3Iky3Vzyc4jYG7y6f5DqfebYMW6hCvLpf9lN6/gPNOb2KjL3hvJ+hbj+
b9EkVAzpw7mW1VHEy+WbtYMPoKy08JTc7zr1tv/vQGr3XExwlC9iixZXMaVt1kP1
TEVHv2FiUOiZsVaqtoFpS/wBvKeQdkzNy+66pRpG9bLuOnL4hlz+rwHkdBmHGk+q
cXdwglqIDqXKlCpIMSkFPH1364KLdJ2qBgWWoWCJjUmgbrA8/LU6DX+GBbEiw45T
PQKP//RMkOrHOYRD33WTU0iKP61zn5+9RD5OLxEUOtCvL7AfB+jt4vYrMTT2U3Kl
OckWxNx55bYLdLfGKtepGV2r5xzce0UMbWQrXQRuka3a/j5VJUTuUgcwgd6FoP4N
4ObW2H1YEtE5M30xpa1kcqJ1RGEWagakISgn2Z3TywIDAQABoxMwETAPBgNVHREE
CDAGhwQKBaxNMA0GCSqGSIb3DQEBCwUAA4ICAQCE2eJVcvsMmJu6xAfoE6/u6BrD
opMicCtlC2qt0BgSIzzDQ/iWjnWKGM1C+pO+2G0WTczj7ugsxjPzhkyBpuEZaWt0
9/tJTKIrgaRZvEe0ifsJxyqL5LJgfxK7TbDPcUBKr1v+TOxPVRq0FuG16x+yka4C
rwxfBHU43FmtEFfgu13r515F3ggXcdlojkce8ZKtTAGEcN0MpbJ6XS90BHU0sy5A
APTm0fR0vM3kg1nuBLbSGF5KfASdw13gb6QsDbll0IqK8LvXYiX5CaVfkAe/pFkO
/2iIxYW74yC2gV+DcFdRPVfFxSKrdg0tDER35OYg1/vXRjV5BWr1EjE3qjrCcUZy
rlF3fms7Arr20ka2nSa8avn4ALpyJZmKasoxNAAsxivingNVZkql48OqsJ3n0qGk
LI6Yu+UM/pc78a3NHsdsCbnf8qvae4oJa1kyiochJu+gUOzHvs4Ydti9iTQn2Byo
2A2LzyVPBmSOhzdQ7SwpvHA4A2ftao+dZoA/+o4rmBtbmgxjpBPyPJTN0ZfKlpKl
Oyi57ov+cJmZctSUbP3M11gBva7aYu1Rd7/eXeCEl1FHhmKL/Ee+UrNZLiwspb2E
Sa+pOHdJX8VgsIYXku2UKaGT2QFITxO7fnxghioxgsyCKrQ+m1gL9vgXj/gJu+48
c+5CZ9SobLdMkVOtQQ==
-----END CERTIFICATE-----

View File

@ -0,0 +1 @@
subjectAltName=IP:10.5.172.77

View File

@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
BHL/JsJ0Be5xM3V4x4PtihQ3Dw546FY=
-----END PRIVATE KEY-----

View File

@ -0,0 +1,27 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIEmzCCAoMCAQAwVjELMAkGA1UEBhMCUlUxEzARBgNVBAgMClNvbWUtU3RhdGUx
ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEPMA0GA1UEAwwGc2Vy
dmVyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvI1fIoEBoAr7v+wS
QyOVUJeN1RgBYx9jWvxPT+BObsJEpSVRA9ViryJcUVoTmkDnwufO52VYULR6XWwr
wXSqx5peElW03IbOUjdpGbB3qmkM3Bp3o53MxNEmKOMTcp4krxokNTPBt34mTX5R
CDzP/jm9qCN2J1VhRstGua0HB2VkuOSrhiCzD9GkR8s8of99XCt4tsQOwN1dowTb
g+JBxvEy4Hw3qAnnEyNIlPyyZwzqJV+V3acnqCemMmDhoNxfXm0ZmzZSTdyJMt1c
8nOI2Bu8un+Q6n3m2DFuoQry6X/ZTev4DzTm9ioy94byfoW4/m/RJFQM6cO5ltVR
xMvlm7WDD6CstPCU3O869bb/70Bq91xMcJQvYosWVzGlbdZD9UxFR79hYlDombFW
qraBaUv8AbynkHZMzcvuuqUaRvWy7jpy+IZc/q8B5HQZhxpPqnF3cIJaiA6lypQq
SDEpBTx9d+uCi3SdqgYFlqFgiY1JoG6wPPy1Og1/hgWxIsOOUz0Cj//0TJDqxzmE
Q991k1NIij+tc5+fvUQ+Ti8RFDrQry+wHwfo7eL2KzE09lNypTnJFsTceeW2C3S3
xirXqRldq+cc3HtFDG1kK10EbpGt2v4+VSVE7lIHMIHehaD+DeDm1th9WBLROTN9
MaWtZHKidURhFmoGpCEoJ9md08sCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4ICAQAb
FDegAoUBz9O4JR1u68IMnGkO5nINGAPQOqf9a2BxGujnSB7Lw6SHukjkUqqgnfQ0
x/aWOI8JVAi/ptscojgMQUDsVNsij5v+jbJE+ZAobxnTmKP0wTc2ktpf4d8UMVc8
gyM85jLHZ8caCcuy0D97W81vgIv33dNHWtP+sfbQhX9wJ2YQTahIC8NpuQfLAOUH
EFxWil0mfN+9vRQ1C5naKtvrOPqyM0RPrWiudIJ5QjI4aSXxUCupxxnaQMoI0Y50
MvVVT3VwWgP+hL4b+yEJFHRpE7BwCZijsLIXkXmVZoveHhiSMYen1HWIP1VMDEHP
CUtG5UQcA78CBS8qg4nyFbDU4hWClAkAt96O8Y2epJYepIoYuBBSEfrgupESMLjS
E9Hfq/H6Ac/Q3zWa320udvA+ysfS8pagkoiH9+TarrsDjhxLjg2h2bGcXKlrsP1R
mRVZwfNOl3/ZNq5HBPb9Z5WXKvcsTCQAlnHJdaSmzdyArB0guwUHg8ZZNZqCdVgL
TPsfE84yI/HlwRfuQILfGxq99p/UYFwnee5CoM/PPvaAT+9z/lykMWZA7osuBcK6
zP8XneGmZOkmez5+YJgSC0xeaDxr2R52eQXlQEJGDbFDtQap/X+cJDGyqmGnbhSu
6XkGy0l8mAkpcurMcy3wWf6+joskZAN4Joi4ZjKsQA==
-----END CERTIFICATE REQUEST-----

View File

@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFjTCCA3WgAwIBAgIUL2Y/QpwqqHyi43PwPeA6ygdPYK4wDQYJKoZIhvcNAQEL
BQAwVjELMAkGA1UEBhMCUlUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEPMA0GA1UEAwwGY2xpZW50MB4XDTIy
MDIxODA5NDMxMFoXDTMyMDIxNjA5NDMxMFowVjELMAkGA1UEBhMCUlUxEzARBgNV
BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
ZDEPMA0GA1UEAwwGY2xpZW50MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
AgEAxO2PSeaiNFMRRiFXpnMw07u6EIdEc1Jx3cPvZjEUg/pdEmMYkrSxr2MeqRkl
tWH8TcIIoiWDLIcM6IU0mF6a5ULu84hFb9b20qRG3wRNb5yO86HnoyzU99t98++a
9iaY1QAt03k8wq4jRjU2k/eoVSoLT5uVP5KxiNzdS2BTHFSsxrt/xcwdgkfJouHN
p+MYUekk6qaQy5fTqTpqdkgO2v/JoYCi0whBNj205d+WnS7xfeyVSJP1OJWHRZ7K
Y+LU6hz6wHIng4s/ag7VdAk0PArWs50BmH5g2zJfvt7VeTQebaJWUtSEY05odOqt
KZteUmmhxW/2M73wGVF3WAJCnaxypsjcmMZFCpMXpwyTFrqobvC3APl6SOP+Ev1M
LxhhCIDuLFu46P55KKEKjUCsYigd1VsHjjvoajGcqlPlMsVHJc9VChsQDz6agzDP
Fb/LyYbrDTTmsI57/s1jAZyemq2SEYPApJvcdZ/ucl741jI0671EZPlip9iUQgt3
MHlc3t53/GtF2W6GF5Fogch7c+0c2BhMupAHAXwfLABvv5X8GDyjsNlwB6ea9jeC
Hw+0rEotZzCXId3daFytGNm1jI216kXLSbvz6uz1wMGS6Hrhk87whgvQ58RMNs1K
SGDFw1WFv+QZeTO7wqcn8Y/eqF7q9RBhOpPMJMX8Sx/UXuECAwEAAaNTMFEwHQYD
VR0OBBYEFCI7Iy7tY0D4HPa9BZCZxYuJ51mZMB8GA1UdIwQYMBaAFCI7Iy7tY0D4
HPa9BZCZxYuJ51mZMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIB
AIKYtBwTp3yvUGSXorV32dnU0Hp0MOie/itgx/la6b3h2bZSoCigKmcmvMaAaNzA
pxeYSsf5wPnONpWfo9hsGrUDMT4ETnXdzA1dbidIrhJbGsY8CN217Qt3YZWNWkrz
xLwxEwAovQZqnGDvtx+tRE8i6YJO6/kca+GB7liHFvUx8zaQ6gCwfloduG8rOAeq
noeCpW/zqYQSQGK35ntQ8MTTRbi7jMOTCikvRlldS73ODQcAR7jywgBYf/i8ANtz
NoWa4KbWuqKsQKMIGOi1fMLMaNlDSzJyw6UJ2GVCcL1NxkCZi0yudfAAxWlRis9G
zLjm7YdNBiC6RVZudGhvzjlsLZpE9DgiwXqcDv3Y1dpstD5ikrNhlQo6THH1YeFy
B8vjVGZZZu4B2JEo+QWH+zFGJosD66YoaKMVuwRPwoGDQoO0Pfbpq41A4KUhB3cf
X49/rbInqwsN5MuGp4l4+T7k7Wm0Y1Qo4FXDVbFxHvvniyHUsZk9Llzf5wBLl84m
xheUGgCHSflfXuuWi76yoADHCv+Eqi4/aLJmkUewKXJlm+XYs9bdBHUI+Y10KmhA
hgcHXF56L+N4mLRwUuLxa5qwQIqNX32+piQoO9opxnVKKCptpATLE30TOMLEXBlp
J+6b1e4BIasAAEGUhTgPj/SLL0u59Bv0K5SlSn7VZ0gI
-----END CERTIFICATE-----

View File

@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
neUhT/t9hHdcMJgoxm2IITf6ip8nTnY=
-----END PRIVATE KEY-----

View File

@ -0,0 +1,36 @@
<clickhouse>
<!-- HTTP API with TLS (HTTPS).
You have to configure certificate to enable this interface.
See the openSSL section below.
-->
<https_port>8443</https_port>
<!-- Native interface with TLS.
You have to configure certificate to enable this interface.
See the openSSL section below.
-->
<!-- <tcp_port_secure>9440</tcp_port_secure> -->
<!-- Used with https_port and tcp_port_secure. Full ssl options list: https://github.com/ClickHouse-Extras/poco/blob/master/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h#L71 -->
<openSSL replace="replace">
<server> <!-- Used for https server AND secure tcp port -->
<certificateFile>/etc/clickhouse-server/config.d/server-cert.pem</certificateFile>
<privateKeyFile>/etc/clickhouse-server/config.d/server-key.pem</privateKeyFile>
<caConfig>/etc/clickhouse-server/config.d/ca-cert.pem</caConfig>
<verificationMode>relaxed</verificationMode>
</server>
<client> <!-- Used for connecting to https dictionary source and secured Zookeeper communication -->
<loadDefaultCAFile>true</loadDefaultCAFile>
<cacheSessions>true</cacheSessions>
<disableProtocols>sslv2,sslv3</disableProtocols>
<preferServerCiphers>true</preferServerCiphers>
<!-- Use for self-signed: <verificationMode>none</verificationMode> -->
<invalidCertificateHandler>
<!-- Use for self-signed: <name>AcceptCertificateHandler</name> -->
<name>RejectCertificateHandler</name>
</invalidCertificateHandler>
</client>
</openSSL>
</clickhouse>

View File

@ -0,0 +1,22 @@
<?xml version="1.0"?>
<clickhouse>
<users>
<john>
<ssl_certificates>
<common_name>client1</common_name>
</ssl_certificates>
</john>
<lucy>
<ssl_certificates>
<common_name>client2</common_name>
<common_name>client3</common_name>
</ssl_certificates>
</lucy>
<peter>
<no_password/>
</peter>
<jane>
<password>qwe123</password>
</jane>
</users>
</clickhouse>

View File

@ -0,0 +1,117 @@
import pytest
from helpers.cluster import ClickHouseCluster
import urllib.request, urllib.parse
import ssl
import os.path
HTTPS_PORT = 8443
NODE_IP = '10.5.172.77' # It's important for the node to work at this IP because 'server-cert.pem' requires that (see server-ext.cnf).
NODE_IP_WITH_HTTPS_PORT = NODE_IP + ':' + str(HTTPS_PORT)
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
cluster = ClickHouseCluster(__file__)
instance = cluster.add_instance('node', ipv4_address=NODE_IP,
main_configs=['configs/ssl_config.xml', 'certs/server-key.pem', 'certs/server-cert.pem', 'certs/ca-cert.pem'],
user_configs=["configs/users_with_ssl_auth.xml"])
@pytest.fixture(scope="module", autouse=True)
def started_cluster():
try:
cluster.start()
yield cluster
finally:
cluster.shutdown()
def get_ssl_context(cert_name):
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.load_verify_locations(cafile=f'{SCRIPT_DIR}/certs/ca-cert.pem')
if cert_name:
context.load_cert_chain(f'{SCRIPT_DIR}/certs/{cert_name}-cert.pem', f'{SCRIPT_DIR}/certs/{cert_name}-key.pem')
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
return context
def execute_query_https(query, user, enable_ssl_auth=True, cert_name=None, password=None):
url = f'https://{NODE_IP_WITH_HTTPS_PORT}/?query={urllib.parse.quote(query)}'
request = urllib.request.Request(url)
request.add_header('X-ClickHouse-User', user)
if enable_ssl_auth:
request.add_header('X-ClickHouse-SSL-Certificate-Auth', 'on')
if password:
request.add_header('X-ClickHouse-Key', password)
response = urllib.request.urlopen(request, context=get_ssl_context(cert_name)).read()
return response.decode('utf-8')
def test_https():
assert execute_query_https("SELECT currentUser()", user="john", cert_name='client1') == "john\n"
assert execute_query_https("SELECT currentUser()", user="lucy", cert_name='client2') == "lucy\n"
assert execute_query_https("SELECT currentUser()", user="lucy", cert_name='client3') == "lucy\n"
def test_https_wrong_cert():
# Wrong certificate: different user's certificate
with pytest.raises(Exception) as err:
execute_query_https("SELECT currentUser()", user="john", cert_name='client2')
assert "HTTP Error 403" in str(err.value)
# Wrong certificate: self-signed certificate.
with pytest.raises(Exception) as err:
execute_query_https("SELECT currentUser()", user="john", cert_name='wrong')
assert "unknown ca" in str(err.value)
# No certificate.
with pytest.raises(Exception) as err:
execute_query_https("SELECT currentUser()", user="john")
assert "HTTP Error 403" in str(err.value)
# No header enabling SSL authentication.
with pytest.raises(Exception) as err:
execute_query_https("SELECT currentUser()", user="john", enable_ssl_auth=False, cert_name='client1')
def test_https_non_ssl_auth():
# Users with non-SSL authentication are allowed, in this case we can skip sending a client certificate at all (because "verificationMode" is set to "relaxed").
#assert execute_query_https("SELECT currentUser()", user="peter", enable_ssl_auth=False) == "peter\n"
assert execute_query_https("SELECT currentUser()", user="jane", enable_ssl_auth=False, password='qwe123') == "jane\n"
# But we still can send a certificate if we want.
assert execute_query_https("SELECT currentUser()", user="peter", enable_ssl_auth=False, cert_name='client1') == "peter\n"
assert execute_query_https("SELECT currentUser()", user="peter", enable_ssl_auth=False, cert_name='client2') == "peter\n"
assert execute_query_https("SELECT currentUser()", user="peter", enable_ssl_auth=False, cert_name='client3') == "peter\n"
assert execute_query_https("SELECT currentUser()", user="jane", enable_ssl_auth=False, password='qwe123', cert_name='client1') == "jane\n"
assert execute_query_https("SELECT currentUser()", user="jane", enable_ssl_auth=False, password='qwe123', cert_name='client2') == "jane\n"
assert execute_query_https("SELECT currentUser()", user="jane", enable_ssl_auth=False, password='qwe123', cert_name='client3') == "jane\n"
# However if we send a certificate it must not be wrong.
with pytest.raises(Exception) as err:
execute_query_https("SELECT currentUser()", user="peter", enable_ssl_auth=False, cert_name='wrong')
assert "unknown ca" in str(err.value)
with pytest.raises(Exception) as err:
execute_query_https("SELECT currentUser()", user="jane", enable_ssl_auth=False, password='qwe123', cert_name='wrong')
assert "unknown ca" in str(err.value)
def test_create_user():
instance.query("CREATE USER emma IDENTIFIED WITH ssl_certificate CN 'client3'")
assert execute_query_https("SELECT currentUser()", user="emma", cert_name='client3') == "emma\n"
assert instance.query("SHOW CREATE USER emma") == "CREATE USER emma IDENTIFIED WITH ssl_certificate CN \\'client3\\'\n"
instance.query("ALTER USER emma IDENTIFIED WITH ssl_certificate CN 'client2'")
assert execute_query_https("SELECT currentUser()", user="emma", cert_name='client2') == "emma\n"
assert instance.query("SHOW CREATE USER emma") == "CREATE USER emma IDENTIFIED WITH ssl_certificate CN \\'client2\\'\n"
with pytest.raises(Exception) as err:
execute_query_https("SELECT currentUser()", user="emma", cert_name='client3')
assert "HTTP Error 403" in str(err.value)
assert instance.query("SHOW CREATE USER lucy") == "CREATE USER lucy IDENTIFIED WITH ssl_certificate CN \\'client2\\', \\'client3\\'\n"
assert instance.query("SELECT name, auth_type, auth_params FROM system.users WHERE name IN ['emma', 'lucy'] ORDER BY name") ==\
"emma\tssl_certificate\t{\"common_names\":[\"client2\"]}\n"\
"lucy\tssl_certificate\t{\"common_names\":[\"client2\",\"client3\"]}\n"

View File

@ -1,35 +1,35 @@
-- default
CREATE ROW POLICY p1_01295 ON db.table AS permissive
CREATE ROW POLICY p1_01295 ON db.table
-- same as default
CREATE ROW POLICY p2_01295 ON db.table AS permissive
CREATE ROW POLICY p3_01295 ON db.table AS permissive
CREATE ROW POLICY p2_01295 ON db.table
CREATE ROW POLICY p3_01295 ON db.table
-- rename
CREATE ROW POLICY p2_01295_renamed ON db.table AS permissive
CREATE ROW POLICY p2_01295_renamed ON db.table
-- filter
CREATE ROW POLICY p1_01295 ON db.table FOR SELECT USING (a < b) AND (c > d) AS permissive
CREATE ROW POLICY p2_01295 ON db.table FOR SELECT USING id = currentUser() AS restrictive
CREATE ROW POLICY p3_01295 ON db.table FOR SELECT USING 1 AS permissive
CREATE ROW POLICY p1_01295 ON db.table FOR SELECT USING 0 AS restrictive
CREATE ROW POLICY p1_01295 ON db.table FOR SELECT USING (a < b) AND (c > d)
CREATE ROW POLICY p2_01295 ON db.table AS restrictive FOR SELECT USING id = currentUser()
CREATE ROW POLICY p3_01295 ON db.table FOR SELECT USING 1
CREATE ROW POLICY p1_01295 ON db.table AS restrictive FOR SELECT USING 0
-- to roles
CREATE ROW POLICY p1_01295 ON db.table AS permissive
CREATE ROW POLICY p2_01295 ON db.table AS permissive TO ALL
CREATE ROW POLICY p3_01295 ON db.table AS permissive TO r1_01295
CREATE ROW POLICY p4_01295 ON db.table AS permissive TO u1_01295
CREATE ROW POLICY p5_01295 ON db.table AS permissive TO r1_01295, u1_01295
CREATE ROW POLICY p6_01295 ON db.table AS permissive TO ALL EXCEPT r1_01295
CREATE ROW POLICY p7_01295 ON db.table AS permissive TO ALL EXCEPT r1_01295, u1_01295
CREATE ROW POLICY p1_01295 ON db.table AS permissive TO u1_01295
CREATE ROW POLICY p2_01295 ON db.table AS permissive
CREATE ROW POLICY p1_01295 ON db.table
CREATE ROW POLICY p2_01295 ON db.table TO ALL
CREATE ROW POLICY p3_01295 ON db.table TO r1_01295
CREATE ROW POLICY p4_01295 ON db.table TO u1_01295
CREATE ROW POLICY p5_01295 ON db.table TO r1_01295, u1_01295
CREATE ROW POLICY p6_01295 ON db.table TO ALL EXCEPT r1_01295
CREATE ROW POLICY p7_01295 ON db.table TO ALL EXCEPT r1_01295, u1_01295
CREATE ROW POLICY p1_01295 ON db.table TO u1_01295
CREATE ROW POLICY p2_01295 ON db.table
-- multiple policies in one command
CREATE ROW POLICY p1_01295 ON db.table FOR SELECT USING 1 AS permissive
CREATE ROW POLICY p2_01295 ON db.table FOR SELECT USING 1 AS permissive
CREATE ROW POLICY p3_01295 ON db.table AS permissive TO u1_01295
CREATE ROW POLICY p3_01295 ON db2.table2 AS permissive TO u1_01295
CREATE ROW POLICY p4_01295 ON db.table FOR SELECT USING a = b AS permissive
CREATE ROW POLICY p5_01295 ON db2.table2 FOR SELECT USING a = b AS permissive
CREATE ROW POLICY p1_01295 ON db.table FOR SELECT USING 1 AS permissive TO ALL
CREATE ROW POLICY p2_01295 ON db.table FOR SELECT USING 1 AS permissive TO ALL
CREATE ROW POLICY p1_01295 ON db.table FOR SELECT USING 1
CREATE ROW POLICY p2_01295 ON db.table FOR SELECT USING 1
CREATE ROW POLICY p3_01295 ON db.table TO u1_01295
CREATE ROW POLICY p3_01295 ON db2.table2 TO u1_01295
CREATE ROW POLICY p4_01295 ON db.table FOR SELECT USING a = b
CREATE ROW POLICY p5_01295 ON db2.table2 FOR SELECT USING a = b
CREATE ROW POLICY p1_01295 ON db.table FOR SELECT USING 1 TO ALL
CREATE ROW POLICY p2_01295 ON db.table FOR SELECT USING 1 TO ALL
-- system.row_policies
p1_01295 ON db.table p1_01295 db table local directory (a < b) AND (c > d) permissive 0 [] []
p2_01295 ON db.table p2_01295 db table local directory id = currentUser() restrictive 0 ['u1_01295'] []
p3_01295 ON db.table p3_01295 db table local directory 1 permissive 1 [] ['r1_01295']
p1_01295 ON db.table p1_01295 db table local directory (a < b) AND (c > d) 0 0 [] []
p2_01295 ON db.table p2_01295 db table local directory id = currentUser() 1 0 ['u1_01295'] []
p3_01295 ON db.table p3_01295 db table local directory 1 0 1 [] ['r1_01295']

View File

@ -72,7 +72,7 @@ SELECT '-- system.row_policies';
CREATE ROW POLICY p1_01295 ON db.table USING a<b AND c>d;
CREATE ROW POLICY p2_01295 ON db.table USING id=currentUser() AS RESTRICTIVE TO u1_01295;
CREATE ROW POLICY p3_01295 ON db.table USING 1 AS PERMISSIVE TO ALL EXCEPT r1_01295;
SELECT name, short_name, database, table, storage, select_filter, kind, apply_to_all, apply_to_list, apply_to_except from system.row_policies WHERE short_name LIKE 'p%\_01295' ORDER BY name;
SELECT name, short_name, database, table, storage, select_filter, is_restrictive, apply_to_all, apply_to_list, apply_to_except from system.row_policies WHERE short_name LIKE 'p%\_01295' ORDER BY name;
DROP ROW POLICY p1_01295, p2_01295, p3_01295 ON db.table;
DROP ROLE r1_01295;

View File

@ -1,20 +1,20 @@
-- one policy
CREATE ROW POLICY p1_01296 ON db_01296.table AS permissive
CREATE ROW POLICY p1_01296 ON db_01296.table AS permissive
CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1 AS permissive
CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1 AS permissive
CREATE ROW POLICY p1_01296 ON db_01296.table
CREATE ROW POLICY p1_01296 ON db_01296.table
CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1
CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1
-- multiple policies
CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1 AS permissive
CREATE ROW POLICY p2_01296 ON db_01296.table FOR SELECT USING 1 AS permissive
CREATE ROW POLICY p3_01296 ON db_01296.table AS permissive TO u1_01296
CREATE ROW POLICY p3_01296 ON db_01296.table2 AS permissive TO u1_01296
CREATE ROW POLICY p4_01296 ON db_01296.table FOR SELECT USING a = b AS permissive
CREATE ROW POLICY p5_01296 ON db_01296.table2 FOR SELECT USING a = b AS permissive
CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1 AS permissive
CREATE ROW POLICY p2_01296 ON db_01296.table FOR SELECT USING 1 AS permissive
CREATE ROW POLICY p3_01296 ON db_01296.table AS permissive TO u1_01296
CREATE ROW POLICY p3_01296 ON db_01296.table2 AS permissive TO u1_01296
CREATE ROW POLICY p4_01296 ON db_01296.table FOR SELECT USING a = b AS permissive
CREATE ROW POLICY p5_01296 ON db_01296.table2 FOR SELECT USING a = b AS permissive
CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1 AS permissive TO ALL
CREATE ROW POLICY p2_01296 ON db_01296.table FOR SELECT USING 1 AS permissive TO ALL
CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1
CREATE ROW POLICY p2_01296 ON db_01296.table FOR SELECT USING 1
CREATE ROW POLICY p3_01296 ON db_01296.table TO u1_01296
CREATE ROW POLICY p3_01296 ON db_01296.table2 TO u1_01296
CREATE ROW POLICY p4_01296 ON db_01296.table FOR SELECT USING a = b
CREATE ROW POLICY p5_01296 ON db_01296.table2 FOR SELECT USING a = b
CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1
CREATE ROW POLICY p2_01296 ON db_01296.table FOR SELECT USING 1
CREATE ROW POLICY p3_01296 ON db_01296.table TO u1_01296
CREATE ROW POLICY p3_01296 ON db_01296.table2 TO u1_01296
CREATE ROW POLICY p4_01296 ON db_01296.table FOR SELECT USING a = b
CREATE ROW POLICY p5_01296 ON db_01296.table2 FOR SELECT USING a = b
CREATE ROW POLICY p1_01296 ON db_01296.table FOR SELECT USING 1 TO ALL
CREATE ROW POLICY p2_01296 ON db_01296.table FOR SELECT USING 1 TO ALL

View File

@ -1 +1 @@
CREATE USER user IDENTIFIED WITH plaintext_password BY 'hello'
CREATE USER user IDENTIFIED WITH plaintext_password BY 'hello'

View File

@ -49,7 +49,7 @@ CREATE TABLE system.replicated_merge_tree_settings\n(\n `name` String,\n `
CREATE TABLE system.replication_queue\n(\n `database` String,\n `table` String,\n `replica_name` String,\n `position` UInt32,\n `node_name` String,\n `type` String,\n `create_time` DateTime,\n `required_quorum` UInt32,\n `source_replica` String,\n `new_part_name` String,\n `parts_to_merge` Array(String),\n `is_detach` UInt8,\n `is_currently_executing` UInt8,\n `num_tries` UInt32,\n `last_exception` String,\n `last_attempt_time` DateTime,\n `num_postponed` UInt32,\n `postpone_reason` String,\n `last_postpone_time` DateTime,\n `merge_type` String\n)\nENGINE = SystemReplicationQueue()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.role_grants\n(\n `user_name` Nullable(String),\n `role_name` Nullable(String),\n `granted_role_name` String,\n `granted_role_is_default` UInt8,\n `with_admin_option` UInt8\n)\nENGINE = SystemRoleGrants()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.roles\n(\n `name` String,\n `id` UUID,\n `storage` String\n)\nENGINE = SystemRoles()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.row_policies\n(\n `name` String,\n `short_name` String,\n `database` String,\n `table` String,\n `id` UUID,\n `storage` String,\n `select_filter` Nullable(String),\n `kind` Enum8(\'permissive\' = 0, \'restrictive\' = 1),\n `apply_to_all` UInt8,\n `apply_to_list` Array(String),\n `apply_to_except` Array(String)\n)\nENGINE = SystemRowPolicies()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.row_policies\n(\n `name` String,\n `short_name` String,\n `database` String,\n `table` String,\n `id` UUID,\n `storage` String,\n `select_filter` Nullable(String),\n `is_restrictive` UInt8,\n `apply_to_all` UInt8,\n `apply_to_list` Array(String),\n `apply_to_except` Array(String)\n)\nENGINE = SystemRowPolicies()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.settings\n(\n `name` String,\n `value` String,\n `changed` UInt8,\n `description` String,\n `min` Nullable(String),\n `max` Nullable(String),\n `readonly` UInt8,\n `type` String\n)\nENGINE = SystemSettings()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.settings_profile_elements\n(\n `profile_name` Nullable(String),\n `user_name` Nullable(String),\n `role_name` Nullable(String),\n `index` UInt64,\n `setting_name` Nullable(String),\n `value` Nullable(String),\n `min` Nullable(String),\n `max` Nullable(String),\n `readonly` Nullable(UInt8),\n `inherit_profile` Nullable(String)\n)\nENGINE = SystemSettingsProfileElements()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.settings_profiles\n(\n `name` String,\n `id` UUID,\n `storage` String,\n `num_elements` UInt64,\n `apply_to_all` UInt8,\n `apply_to_list` Array(String),\n `apply_to_except` Array(String)\n)\nENGINE = SystemSettingsProfiles()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
@ -60,7 +60,7 @@ CREATE TABLE system.table_functions\n(\n `name` String\n)\nENGINE = SystemTab
CREATE TABLE system.tables\n(\n `database` String,\n `name` String,\n `uuid` UUID,\n `engine` String,\n `is_temporary` UInt8,\n `data_paths` Array(String),\n `metadata_path` String,\n `metadata_modification_time` DateTime,\n `dependencies_database` Array(String),\n `dependencies_table` Array(String),\n `create_table_query` String,\n `engine_full` String,\n `as_select` String,\n `partition_key` String,\n `sorting_key` String,\n `primary_key` String,\n `sampling_key` String,\n `storage_policy` String,\n `total_rows` Nullable(UInt64),\n `total_bytes` Nullable(UInt64),\n `lifetime_rows` Nullable(UInt64),\n `lifetime_bytes` Nullable(UInt64),\n `comment` String,\n `has_own_data` UInt8,\n `loading_dependencies_database` Array(String),\n `loading_dependencies_table` Array(String),\n `loading_dependent_database` Array(String),\n `loading_dependent_table` Array(String),\n `table` String\n)\nENGINE = SystemTables()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.time_zones\n(\n `time_zone` String\n)\nENGINE = SystemTimeZones()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.user_directories\n(\n `name` String,\n `type` String,\n `params` String,\n `precedence` UInt64\n)\nENGINE = SystemUserDirectories()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.users\n(\n `name` String,\n `id` UUID,\n `storage` String,\n `auth_type` Enum8(\'no_password\' = 0, \'plaintext_password\' = 1, \'sha256_password\' = 2, \'double_sha1_password\' = 3, \'ldap\' = 4, \'kerberos\' = 5),\n `auth_params` String,\n `host_ip` Array(String),\n `host_names` Array(String),\n `host_names_regexp` Array(String),\n `host_names_like` Array(String),\n `default_roles_all` UInt8,\n `default_roles_list` Array(String),\n `default_roles_except` Array(String),\n `grantees_any` UInt8,\n `grantees_list` Array(String),\n `grantees_except` Array(String),\n `default_database` String\n)\nENGINE = SystemUsers()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.users\n(\n `name` String,\n `id` UUID,\n `storage` String,\n `auth_type` Enum8(\'no_password\' = 0, \'plaintext_password\' = 1, \'sha256_password\' = 2, \'double_sha1_password\' = 3, \'ldap\' = 4, \'kerberos\' = 5, \'ssl_certificate\' = 6),\n `auth_params` String,\n `host_ip` Array(String),\n `host_names` Array(String),\n `host_names_regexp` Array(String),\n `host_names_like` Array(String),\n `default_roles_all` UInt8,\n `default_roles_list` Array(String),\n `default_roles_except` Array(String),\n `grantees_any` UInt8,\n `grantees_list` Array(String),\n `grantees_except` Array(String),\n `default_database` String\n)\nENGINE = SystemUsers()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.warnings\n(\n `message` String\n)\nENGINE = SystemWarnings()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.zeros\n(\n `zero` UInt8\n)\nENGINE = SystemZeros()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'
CREATE TABLE system.zeros_mt\n(\n `zero` UInt8\n)\nENGINE = SystemZeros()\nCOMMENT \'SYSTEM TABLE is built on the fly.\'

View File

@ -1,33 +0,0 @@
None
1
2
3
4
R1: x == 1
1
R1, R2: (x == 1) OR (x == 2)
1
2
R1, R2, R3: (x == 1) OR (x == 2) OR (x == 3)
1
2
3
R1, R2, R3, R4: ((x == 1) OR (x == 2) OR (x == 3)) AND (x <= 2)
1
2
R1, R2, R3, R4, R5: ((x == 1) OR (x == 2) OR (x == 3)) AND (x <= 2) AND (x >= 2)
2
R2, R3, R4, R5: ((x == 2) OR (x == 3)) AND (x <= 2) AND (x >= 2)
2
R3, R4, R5: (x == 3) AND (x <= 2) AND (x >= 2)
R4, R5: (x <= 2) AND (x >= 2)
2
R5: (x >= 2)
2
3
4
None
1
2
3
4

View File

@ -1,55 +0,0 @@
DROP TABLE IF EXISTS 02131_multiple_row_policies_on_same_column;
CREATE TABLE 02131_multiple_row_policies_on_same_column (x UInt8) ENGINE = MergeTree ORDER BY x;
INSERT INTO 02131_multiple_row_policies_on_same_column VALUES (1), (2), (3), (4);
DROP ROW POLICY IF EXISTS 02131_filter_1 ON 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY IF EXISTS 02131_filter_2 ON 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY IF EXISTS 02131_filter_3 ON 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY IF EXISTS 02131_filter_4 ON 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY IF EXISTS 02131_filter_5 ON 02131_multiple_row_policies_on_same_column;
SELECT 'None';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_1 ON 02131_multiple_row_policies_on_same_column USING x=1 AS permissive TO ALL;
SELECT 'R1: x == 1';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_2 ON 02131_multiple_row_policies_on_same_column USING x=2 AS permissive TO ALL;
SELECT 'R1, R2: (x == 1) OR (x == 2)';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_3 ON 02131_multiple_row_policies_on_same_column USING x=3 AS permissive TO ALL;
SELECT 'R1, R2, R3: (x == 1) OR (x == 2) OR (x == 3)';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_4 ON 02131_multiple_row_policies_on_same_column USING x<=2 AS restrictive TO ALL;
SELECT 'R1, R2, R3, R4: ((x == 1) OR (x == 2) OR (x == 3)) AND (x <= 2)';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_5 ON 02131_multiple_row_policies_on_same_column USING x>=2 AS restrictive TO ALL;
SELECT 'R1, R2, R3, R4, R5: ((x == 1) OR (x == 2) OR (x == 3)) AND (x <= 2) AND (x >= 2)';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_1 ON 02131_multiple_row_policies_on_same_column;
SELECT 'R2, R3, R4, R5: ((x == 2) OR (x == 3)) AND (x <= 2) AND (x >= 2)';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_2 ON 02131_multiple_row_policies_on_same_column;
SELECT 'R3, R4, R5: (x == 3) AND (x <= 2) AND (x >= 2)';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_3 ON 02131_multiple_row_policies_on_same_column;
SELECT 'R4, R5: (x <= 2) AND (x >= 2)';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_4 ON 02131_multiple_row_policies_on_same_column;
SELECT 'R5: (x >= 2)';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_5 ON 02131_multiple_row_policies_on_same_column;
SELECT 'None';
SELECT * FROM 02131_multiple_row_policies_on_same_column;
DROP TABLE 02131_multiple_row_policies_on_same_column;

View File

@ -0,0 +1,8 @@
4
1
2
3
3
3
3
4

View File

@ -0,0 +1,30 @@
DROP TABLE IF EXISTS 02131_multiply_row_policies_on_same_column;
CREATE TABLE 02131_multiply_row_policies_on_same_column (x UInt8) ENGINE = MergeTree ORDER BY x;
INSERT INTO 02131_multiply_row_policies_on_same_column VALUES (1), (2), (3), (4);
DROP ROW POLICY IF EXISTS 02131_filter_1 ON 02131_multiply_row_policies_on_same_column;
DROP ROW POLICY IF EXISTS 02131_filter_2 ON 02131_multiply_row_policies_on_same_column;
DROP ROW POLICY IF EXISTS 02131_filter_3 ON 02131_multiply_row_policies_on_same_column;
SELECT count() FROM 02131_multiply_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_1 ON 02131_multiply_row_policies_on_same_column USING x=1 TO ALL;
SELECT count() FROM 02131_multiply_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_2 ON 02131_multiply_row_policies_on_same_column USING x=2 TO ALL;
SELECT count() FROM 02131_multiply_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_3 ON 02131_multiply_row_policies_on_same_column USING x=3 TO ALL;
SELECT count() FROM 02131_multiply_row_policies_on_same_column;
SELECT count() FROM 02131_multiply_row_policies_on_same_column;
CREATE ROW POLICY 02131_filter_4 ON 02131_multiply_row_policies_on_same_column USING x<4 AS RESTRICTIVE TO ALL;
SELECT count() FROM 02131_multiply_row_policies_on_same_column;
SELECT count() FROM 02131_multiply_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_1 ON 02131_multiply_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_2 ON 02131_multiply_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_3 ON 02131_multiply_row_policies_on_same_column;
DROP ROW POLICY 02131_filter_4 ON 02131_multiply_row_policies_on_same_column;
SELECT count() FROM 02131_multiply_row_policies_on_same_column;
DROP TABLE 02131_multiply_row_policies_on_same_column;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 554 B

View File

@ -1,12 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="700px" height="320px" viewBox="0 0 700 320" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Artboard</title>
<g id="Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Quote-Panel-BG" fill="#FF8C00">
<path d="M577.058824,0 L577.058824,96.5483699 L576.887,96.548 L576.880049,97.4482487 C576.317392,132.334805 548.290575,160.5098 513.587495,161.075432 L512.523092,161.084101 L512.523092,117.946846 C524.315884,117.946846 533.886494,108.382248 533.977629,96.5487133 L480,96.5483699 L480,0 L577.058824,0 Z" id="Combined-Shape"></path>
<path d="M700,0 L700,96.5483699 L699.828176,96.548 L699.821226,97.4482487 C699.258568,132.334805 671.231751,160.5098 636.528671,161.075432 L635.464269,161.084101 L635.464269,117.946846 C647.257061,117.946846 656.82767,108.382248 656.918806,96.5487133 L602.941176,96.5483699 L602.941176,0 L700,0 Z" id="Combined-Shape"></path>
<path d="M220,159 L220,255.54837 L219.828176,255.548 L219.821226,256.448249 C219.258568,291.334805 191.231751,319.5098 156.528671,320.075432 L155.464269,320.084101 L155.464269,276.946846 C167.257061,276.946846 176.82767,267.382248 176.918806,255.548713 L122.941176,255.54837 L122.941176,159 L220,159 Z" id="Combined-Shape" transform="translate(171.470588, 239.500000) scale(-1, 1) translate(-171.470588, -239.500000) "></path>
<path d="M97.0588235,159 L97.0588235,255.54837 L96.887,255.548 L96.8800492,256.448249 C96.3173916,291.334805 68.2905748,319.5098 33.587495,320.075432 L32.5230924,320.084101 L32.5230924,276.946846 C44.3158844,276.946846 53.8864936,267.382248 53.9776294,255.548713 L-7.10542736e-15,255.54837 L-7.10542736e-15,159 L97.0588235,159 Z" id="Combined-Shape" transform="translate(48.529412, 239.500000) scale(-1, 1) translate(-48.529412, -239.500000) "></path>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="700" height="320" version="1.1" viewBox="0 0 700 320"><title>Artboard</title><g id="Artboard" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="Quote-Panel-BG" fill="#FF8C00"><path id="Combined-Shape" d="M577.058824,0 L577.058824,96.5483699 L576.887,96.548 L576.880049,97.4482487 C576.317392,132.334805 548.290575,160.5098 513.587495,161.075432 L512.523092,161.084101 L512.523092,117.946846 C524.315884,117.946846 533.886494,108.382248 533.977629,96.5487133 L480,96.5483699 L480,0 L577.058824,0 Z"/><path id="Combined-Shape" d="M700,0 L700,96.5483699 L699.828176,96.548 L699.821226,97.4482487 C699.258568,132.334805 671.231751,160.5098 636.528671,161.075432 L635.464269,161.084101 L635.464269,117.946846 C647.257061,117.946846 656.82767,108.382248 656.918806,96.5487133 L602.941176,96.5483699 L602.941176,0 L700,0 Z"/><path id="Combined-Shape" d="M220,159 L220,255.54837 L219.828176,255.548 L219.821226,256.448249 C219.258568,291.334805 191.231751,319.5098 156.528671,320.075432 L155.464269,320.084101 L155.464269,276.946846 C167.257061,276.946846 176.82767,267.382248 176.918806,255.548713 L122.941176,255.54837 L122.941176,159 L220,159 Z" transform="translate(171.470588, 239.500000) scale(-1, 1) translate(-171.470588, -239.500000)"/><path id="Combined-Shape" d="M97.0588235,159 L97.0588235,255.54837 L96.887,255.548 L96.8800492,256.448249 C96.3173916,291.334805 68.2905748,319.5098 33.587495,320.075432 L32.5230924,320.084101 L32.5230924,276.946846 C44.3158844,276.946846 53.8864936,267.382248 53.9776294,255.548713 L-7.10542736e-15,255.54837 L-7.10542736e-15,159 L97.0588235,159 Z" transform="translate(48.529412, 239.500000) scale(-1, 1) translate(-48.529412, -239.500000)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,17 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon-arrow</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Homepage" transform="translate(-557.000000, -2491.000000)" stroke="#212529" stroke-width="2">
<g id="Page/Use-Cases" transform="translate(0.000000, 2108.000000)">
<g id="Row-1" transform="translate(185.000000, 134.000000)">
<g id="Link/Read" transform="translate(222.000000, 247.000000)">
<g id="icon-arrow" transform="translate(150.000000, 3.000000)">
<path d="M6,0 L12,6 L6,12 M12,6 L0,6" id="Path-39"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="14" version="1.1" viewBox="0 0 14 14"><title>icon-arrow</title><g id="Page-1" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="Homepage" stroke="#212529" stroke-width="2" transform="translate(-557.000000, -2491.000000)"><g id="Page/Use-Cases" transform="translate(0.000000, 2108.000000)"><g id="Row-1" transform="translate(185.000000, 134.000000)"><g id="Link/Read" transform="translate(222.000000, 247.000000)"><g id="icon-arrow" transform="translate(150.000000, 3.000000)"><path id="Path-39" d="M6,0 L12,6 L6,12 M12,6 L0,6"/></g></g></g></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 944 B

After

Width:  |  Height:  |  Size: 680 B

View File

@ -1,14 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="18px" height="14px" viewBox="0 0 18 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon-blog</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="Link/Blog" transform="translate(0.870000, 1.375000)" stroke="#000000" stroke-width="1.25">
<g id="Icon/News">
<line x1="6.25" y1="4.40736607" x2="12.5" y2="4.40736607" id="Path"></line>
<line x1="6.25" y1="6.90736607" x2="12.5" y2="6.90736607" id="Path"></line>
<path d="M1.25,11.25 C1.94035594,11.25 2.5,10.6903559 2.5,10 L2.5,0.625 C2.5,0.279822031 2.77982203,0 3.125,0 L15.625,0 C15.970178,0 16.25,0.279822031 16.25,0.625 L16.25,10 C16.25,10.6903559 15.6903559,11.25 15,11.25 L1.25,11.25 Z" id="Path"></path>
<path d="M1.25,11.25 C0.559644063,11.25 0,10.6903559 0,10 L0,2.5" id="Path"></path>
</g>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="18" height="14" version="1.1" viewBox="0 0 18 14"><title>icon-blog</title><g id="Page-1" fill="none" fill-rule="evenodd" stroke="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"><g id="Link/Blog" stroke="#000" stroke-width="1.25" transform="translate(0.870000, 1.375000)"><g id="Icon/News"><line id="Path" x1="6.25" x2="12.5" y1="4.407" y2="4.407"/><line id="Path" x1="6.25" x2="12.5" y1="6.907" y2="6.907"/><path id="Path" d="M1.25,11.25 C1.94035594,11.25 2.5,10.6903559 2.5,10 L2.5,0.625 C2.5,0.279822031 2.77982203,0 3.125,0 L15.625,0 C15.970178,0 16.25,0.279822031 16.25,0.625 L16.25,10 C16.25,10.6903559 15.6903559,11.25 15,11.25 L1.25,11.25 Z"/><path id="Path" d="M1.25,11.25 C0.559644063,11.25 0,10.6903559 0,10 L0,2.5"/></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 857 B

View File

@ -1,15 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon-facebook-gray</title>
<defs>
<path d="M24,12.0730223 C24,5.40365112 18.6290323,0 12,0 C5.37096774,0 0,5.40365112 0,12.0730223 C0,18.0988235 4.38822581,23.0935497 10.125,24 L10.125,15.563002 L7.0766129,15.563002 L7.0766129,12.0730223 L10.125,12.0730223 L10.125,9.41306288 C10.125,6.38750507 11.9153226,4.71626775 14.6574194,4.71626775 C15.9706452,4.71626775 17.343871,4.95188641 17.343871,4.95188641 L17.343871,7.92146045 L15.8303226,7.92146045 C14.34,7.92146045 13.875,8.85225152 13.875,9.80689655 L13.875,12.0730223 L17.2030645,12.0730223 L16.6708065,15.563002 L13.875,15.563002 L13.875,24 C19.6117742,23.0935497 24,18.0988235 24,12.0730223 Z" id="path-1"></path>
</defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Logo">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Brands/facebook" fill="#6C757D" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" version="1.1" viewBox="0 0 24 24"><title>icon-facebook-gray</title><defs><path id="path-1" d="M24,12.0730223 C24,5.40365112 18.6290323,0 12,0 C5.37096774,0 0,5.40365112 0,12.0730223 C0,18.0988235 4.38822581,23.0935497 10.125,24 L10.125,15.563002 L7.0766129,15.563002 L7.0766129,12.0730223 L10.125,12.0730223 L10.125,9.41306288 C10.125,6.38750507 11.9153226,4.71626775 14.6574194,4.71626775 C15.9706452,4.71626775 17.343871,4.95188641 17.343871,4.95188641 L17.343871,7.92146045 L15.8303226,7.92146045 C14.34,7.92146045 13.875,8.85225152 13.875,9.80689655 L13.875,12.0730223 L17.2030645,12.0730223 L16.6708065,15.563002 L13.875,15.563002 L13.875,24 C19.6117742,23.0935497 24,18.0988235 24,12.0730223 Z"/></defs><g id="Symbols" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="Logo"><mask id="mask-2" fill="#fff"><use xlink:href="#path-1"/></mask><use id="Brands/facebook" fill="#6C757D" fill-rule="nonzero" xlink:href="#path-1"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1,19 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="81px" height="81px" viewBox="0 0 81 81" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Group</title>
<defs>
<polygon id="path-1" points="4.44115232e-15 0 80 0 80 79.5155966 4.44115232e-15 79.5155966"></polygon>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group" transform="translate(0.060000, 0.040000)">
<g id="Group-3">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Clip-2"></g>
<path d="M80,39.9992187 C80,17.906518 62.0903569,-0.00312518312 39.9976561,-0.00312518312 C17.9049554,-0.00312518312 -0.00468777467,17.906518 -0.00468777467,39.9992187 C-0.00468777467,59.9655449 14.6235912,76.5146395 33.7472899,79.5155966 L33.7472899,51.5623962 L23.5904448,51.5623962 L23.5904448,39.9992187 L33.7472899,39.9992187 L33.7472899,31.1862023 C33.7472899,21.1606149 39.7193586,15.6227904 48.856769,15.6227904 C53.2333535,15.6227904 57.8111999,16.4040862 57.8111999,16.4040862 L57.8111999,26.248413 L52.7669981,26.248413 C47.7977225,26.248413 46.2480223,29.331953 46.2480223,32.4954197 L46.2480223,39.9992187 L57.3424224,39.9992187 L55.568881,51.5623962 L46.2480223,51.5623962 L46.2480223,79.5155966 C65.371721,76.5146395 80,59.9655449 80,39.9992187" id="Fill-1" fill="#1877F2" mask="url(#mask-2)"></path>
</g>
<path d="M55.568881,51.5623962 L57.3424224,39.9992187 L46.2480223,39.9992187 L46.2480223,32.4954197 C46.2480223,29.331953 47.7977225,26.248413 52.7669981,26.248413 L57.8111999,26.248413 L57.8111999,16.4040862 C57.8111999,16.4040862 53.2333535,15.6227904 48.856769,15.6227904 C39.7193586,15.6227904 33.7472899,21.1606149 33.7472899,31.1862023 L33.7472899,39.9992187 L23.5904448,39.9992187 L23.5904448,51.5623962 L33.7472899,51.5623962 L33.7472899,79.5155966 C35.7838936,79.8351466 37.8712815,80.0015626 39.9976561,80.0015626 C42.1240307,80.0015626 44.2114186,79.8351466 46.2480223,79.5155966 L46.2480223,51.5623962 L55.568881,51.5623962" id="Fill-4" fill="#FFFFFF"></path>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81" version="1.1" viewBox="0 0 81 81"><title>Group</title><defs><polygon id="path-1" points="0 0 80 0 80 79.516 0 79.516"/></defs><g id="Page-1" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="Group" transform="translate(0.060000, 0.040000)"><g id="Group-3"><mask id="mask-2" fill="#fff"><use xlink:href="#path-1"/></mask><path id="Fill-1" fill="#1877F2" d="M80,39.9992187 C80,17.906518 62.0903569,-0.00312518312 39.9976561,-0.00312518312 C17.9049554,-0.00312518312 -0.00468777467,17.906518 -0.00468777467,39.9992187 C-0.00468777467,59.9655449 14.6235912,76.5146395 33.7472899,79.5155966 L33.7472899,51.5623962 L23.5904448,51.5623962 L23.5904448,39.9992187 L33.7472899,39.9992187 L33.7472899,31.1862023 C33.7472899,21.1606149 39.7193586,15.6227904 48.856769,15.6227904 C53.2333535,15.6227904 57.8111999,16.4040862 57.8111999,16.4040862 L57.8111999,26.248413 L52.7669981,26.248413 C47.7977225,26.248413 46.2480223,29.331953 46.2480223,32.4954197 L46.2480223,39.9992187 L57.3424224,39.9992187 L55.568881,51.5623962 L46.2480223,51.5623962 L46.2480223,79.5155966 C65.371721,76.5146395 80,59.9655449 80,39.9992187" mask="url(#mask-2)"/></g><path id="Fill-4" fill="#FFF" d="M55.568881,51.5623962 L57.3424224,39.9992187 L46.2480223,39.9992187 L46.2480223,32.4954197 C46.2480223,29.331953 47.7977225,26.248413 52.7669981,26.248413 L57.8111999,26.248413 L57.8111999,16.4040862 C57.8111999,16.4040862 53.2333535,15.6227904 48.856769,15.6227904 C39.7193586,15.6227904 33.7472899,21.1606149 33.7472899,31.1862023 L33.7472899,39.9992187 L23.5904448,39.9992187 L23.5904448,51.5623962 L33.7472899,51.5623962 L33.7472899,79.5155966 C35.7838936,79.8351466 37.8712815,80.0015626 39.9976561,80.0015626 C42.1240307,80.0015626 44.2114186,79.8351466 46.2480223,79.5155966 L46.2480223,51.5623962 L55.568881,51.5623962"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,9 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="82px" height="80px" viewBox="0 0 82 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon-github</title>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon-github" fill="#212529" fill-rule="nonzero">
<path d="M36.3976019,0.285587315 C17.4993108,2.34863347 2.29853201,17.6152782 0.244369937,36.1826935 C-1.80979214,55.5751211 9.28268307,72.9047088 26.1267915,79.5064565 C27.3592888,79.9190657 28.591786,79.0938472 28.591786,77.4434103 L28.591786,70.8416626 C28.591786,70.8416626 26.9484564,71.2542719 24.8942943,71.2542719 C19.1426405,71.2542719 16.677646,66.3029611 16.2668136,63.4146965 C15.8559812,61.7642595 15.0343163,60.5264319 13.8018191,59.2886042 C12.5693218,58.8759949 12.1584894,58.8762012 12.1584894,58.463592 C12.1584894,57.6383735 13.3909867,57.6381672 13.8018191,57.6381672 C16.2668136,57.6381672 18.3209757,60.5264319 19.1426405,61.7642595 C21.1968026,65.0651334 23.6617971,65.8903519 24.8942943,65.8903519 C26.537624,65.8903519 27.7701212,65.4777426 28.591786,65.0651334 C29.0026185,62.1768688 30.2351157,59.2886042 32.7001102,57.6381672 C23.2509646,55.5751211 16.2668136,50.2114074 16.2668136,41.1340043 C16.2668136,36.5953028 18.3209757,32.0566012 21.1968026,28.7557274 C20.7859702,27.9305089 20.3751377,25.8674628 20.3751377,22.9791982 C20.3751377,21.3287612 20.3751377,19.2657151 21.1968026,17.6152782 C21.1968026,16.7900597 22.0184674,16.3774505 22.4292998,16.3774505 L22.8401322,16.3774505 C24.8942943,16.7900597 29.0026185,18.0278874 32.7001102,21.7413705 C35.1651047,20.916152 38.0409316,20.5035428 40.9167585,20.5035428 C43.7925854,20.5035428 46.6684123,20.916152 49.1334068,21.7413705 C52.8308985,18.0278874 57.3500551,16.7900597 59.4042172,16.3774505 L59.8150496,16.3774505 C60.6367144,16.3774505 61.0475468,16.7900597 61.4583792,17.6152782 C61.4583792,19.2657151 61.4583792,21.3287612 61.4583792,22.9791982 C61.4583792,26.280072 61.0475468,27.9305089 60.6367144,28.7557274 C63.5125413,32.0566012 65.5667034,36.1826935 65.5667034,41.1340043 C65.5667034,50.2114074 58.5825523,55.5751211 49.1334068,57.6381672 C51.5984013,59.7012134 53.2417309,63.4146965 53.2417309,67.1281795 L53.2417309,77.8560195 C53.2417309,79.0938472 54.4742282,80.3316749 56.1175578,79.9190657 C71.3183572,73.7299272 82,58.8759949 82,41.5466135 C82,16.7900597 61.0475468,-2.6026773 36.3976019,0.285587315 Z" id="Path"></path>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="82" height="80" version="1.1" viewBox="0 0 82 80"><title>icon-github</title><g id="Symbols" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="icon-github" fill="#212529" fill-rule="nonzero"><path id="Path" d="M36.3976019,0.285587315 C17.4993108,2.34863347 2.29853201,17.6152782 0.244369937,36.1826935 C-1.80979214,55.5751211 9.28268307,72.9047088 26.1267915,79.5064565 C27.3592888,79.9190657 28.591786,79.0938472 28.591786,77.4434103 L28.591786,70.8416626 C28.591786,70.8416626 26.9484564,71.2542719 24.8942943,71.2542719 C19.1426405,71.2542719 16.677646,66.3029611 16.2668136,63.4146965 C15.8559812,61.7642595 15.0343163,60.5264319 13.8018191,59.2886042 C12.5693218,58.8759949 12.1584894,58.8762012 12.1584894,58.463592 C12.1584894,57.6383735 13.3909867,57.6381672 13.8018191,57.6381672 C16.2668136,57.6381672 18.3209757,60.5264319 19.1426405,61.7642595 C21.1968026,65.0651334 23.6617971,65.8903519 24.8942943,65.8903519 C26.537624,65.8903519 27.7701212,65.4777426 28.591786,65.0651334 C29.0026185,62.1768688 30.2351157,59.2886042 32.7001102,57.6381672 C23.2509646,55.5751211 16.2668136,50.2114074 16.2668136,41.1340043 C16.2668136,36.5953028 18.3209757,32.0566012 21.1968026,28.7557274 C20.7859702,27.9305089 20.3751377,25.8674628 20.3751377,22.9791982 C20.3751377,21.3287612 20.3751377,19.2657151 21.1968026,17.6152782 C21.1968026,16.7900597 22.0184674,16.3774505 22.4292998,16.3774505 L22.8401322,16.3774505 C24.8942943,16.7900597 29.0026185,18.0278874 32.7001102,21.7413705 C35.1651047,20.916152 38.0409316,20.5035428 40.9167585,20.5035428 C43.7925854,20.5035428 46.6684123,20.916152 49.1334068,21.7413705 C52.8308985,18.0278874 57.3500551,16.7900597 59.4042172,16.3774505 L59.8150496,16.3774505 C60.6367144,16.3774505 61.0475468,16.7900597 61.4583792,17.6152782 C61.4583792,19.2657151 61.4583792,21.3287612 61.4583792,22.9791982 C61.4583792,26.280072 61.0475468,27.9305089 60.6367144,28.7557274 C63.5125413,32.0566012 65.5667034,36.1826935 65.5667034,41.1340043 C65.5667034,50.2114074 58.5825523,55.5751211 49.1334068,57.6381672 C51.5984013,59.7012134 53.2417309,63.4146965 53.2417309,67.1281795 L53.2417309,77.8560195 C53.2417309,79.0938472 54.4742282,80.3316749 56.1175578,79.9190657 C71.3183572,73.7299272 82,58.8759949 82,41.5466135 C82,16.7900597 61.0475468,-2.6026773 36.3976019,0.285587315 Z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -1,12 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="80px" height="80px" viewBox="0 0 80 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon-google</title>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon-google" fill-rule="nonzero">
<path d="M79.222,32.1658392 L76,32.1658392 L76,31.99984 L40,31.99984 L40,47.99976 L62.606,47.99976 C59.308,57.3137134 50.446,63.99968 40,63.99968 C26.746,63.99968 16,53.2537337 16,39.9998 C16,26.7458663 26.746,15.99992 40,15.99992 C46.118,15.99992 51.684,18.3079085 55.922,22.0778896 L67.236,10.7639462 C60.092,4.10597947 50.536,0 40,0 C17.91,0 0,17.9099105 0,39.9998 C0,62.0896896 17.91,79.9996 40,79.9996 C62.09,79.9996 80,62.0896896 80,39.9998 C80,37.3178134 79.724,34.6998265 79.222,32.1658392 Z" id="Path" fill="#FFC107"></path>
<path d="M4.60938,21.3818931 L17.7514,31.0198449 C21.3074,22.2158889 29.9194,15.99992 39.9974,15.99992 C46.1154,15.99992 51.6814,18.3079085 55.9194,22.0778896 L67.2334,10.7639462 C60.0894,4.10597947 50.5334,0 39.9974,0 C24.6334,0 11.30938,8.67395663 4.60938,21.3818931 Z" id="Path" fill="#FF3D00"></path>
<path d="M39.9996,80 C50.3316,80 59.7196,76.0460198 66.8176,69.6160519 L54.4376,59.1401043 C50.4216,62.1820891 45.4296,64.00008 39.9996,64.00008 C29.5956,64.00008 20.7616,57.3661132 17.4336,48.1081595 L4.38964,58.1581092 C11.00964,71.1120444 24.4536,80 39.9996,80 Z" id="Path" fill="#4CAF50"></path>
<path d="M79.222,32.1658392 L76,32.1658392 L76,31.99984 L40,31.99984 L40,47.99976 L62.606,47.99976 C61.022,52.4737376 58.144,56.3317183 54.432,59.1417043 C54.434,59.1397043 54.436,59.1397043 54.438,59.1377043 L66.818,69.6136519 C65.942,70.409648 80,59.9997 80,39.9998 C80,37.3178134 79.724,34.6998265 79.222,32.1658392 Z" id="Path" fill="#1976D2"></path>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="80" height="80" version="1.1" viewBox="0 0 80 80"><title>icon-google</title><g id="Symbols" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="icon-google" fill-rule="nonzero"><path id="Path" fill="#FFC107" d="M79.222,32.1658392 L76,32.1658392 L76,31.99984 L40,31.99984 L40,47.99976 L62.606,47.99976 C59.308,57.3137134 50.446,63.99968 40,63.99968 C26.746,63.99968 16,53.2537337 16,39.9998 C16,26.7458663 26.746,15.99992 40,15.99992 C46.118,15.99992 51.684,18.3079085 55.922,22.0778896 L67.236,10.7639462 C60.092,4.10597947 50.536,0 40,0 C17.91,0 0,17.9099105 0,39.9998 C0,62.0896896 17.91,79.9996 40,79.9996 C62.09,79.9996 80,62.0896896 80,39.9998 C80,37.3178134 79.724,34.6998265 79.222,32.1658392 Z"/><path id="Path" fill="#FF3D00" d="M4.60938,21.3818931 L17.7514,31.0198449 C21.3074,22.2158889 29.9194,15.99992 39.9974,15.99992 C46.1154,15.99992 51.6814,18.3079085 55.9194,22.0778896 L67.2334,10.7639462 C60.0894,4.10597947 50.5334,0 39.9974,0 C24.6334,0 11.30938,8.67395663 4.60938,21.3818931 Z"/><path id="Path" fill="#4CAF50" d="M39.9996,80 C50.3316,80 59.7196,76.0460198 66.8176,69.6160519 L54.4376,59.1401043 C50.4216,62.1820891 45.4296,64.00008 39.9996,64.00008 C29.5956,64.00008 20.7616,57.3661132 17.4336,48.1081595 L4.38964,58.1581092 C11.00964,71.1120444 24.4536,80 39.9996,80 Z"/><path id="Path" fill="#1976D2" d="M79.222,32.1658392 L76,32.1658392 L76,31.99984 L40,31.99984 L40,47.99976 L62.606,47.99976 C61.022,52.4737376 58.144,56.3317183 54.432,59.1417043 C54.434,59.1397043 54.436,59.1397043 54.438,59.1377043 L66.818,69.6136519 C65.942,70.409648 80,59.9997 80,39.9998 C80,37.3178134 79.724,34.6998265 79.222,32.1658392 Z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1,13 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon-linkedin-gray</title>
<defs>
<path d="M22.2857143,0 L1.70892857,0 C0.766071429,0 0,0.776785714 0,1.73035714 L0,22.2696429 C0,23.2232143 0.766071429,24 1.70892857,24 L22.2857143,24 C23.2285714,24 24,23.2232143 24,22.2696429 L24,1.73035714 C24,0.776785714 23.2285714,0 22.2857143,0 Z M7.25357143,20.5714286 L3.69642857,20.5714286 L3.69642857,9.11785714 L7.25892857,9.11785714 L7.25892857,20.5714286 L7.25357143,20.5714286 Z M5.475,7.55357143 C4.33392857,7.55357143 3.4125,6.62678571 3.4125,5.49107143 C3.4125,4.35535714 4.33392857,3.42857143 5.475,3.42857143 C6.61071429,3.42857143 7.5375,4.35535714 7.5375,5.49107143 C7.5375,6.63214286 6.61607143,7.55357143 5.475,7.55357143 L5.475,7.55357143 Z M20.5875,20.5714286 L17.0303571,20.5714286 L17.0303571,15 C17.0303571,13.6714286 17.0035714,11.9625 15.1821429,11.9625 C13.3285714,11.9625 13.0446429,13.4089286 13.0446429,14.9035714 L13.0446429,20.5714286 L9.4875,20.5714286 L9.4875,9.11785714 L12.9,9.11785714 L12.9,10.6821429 L12.9482143,10.6821429 C13.425,9.78214286 14.5875,8.83392857 16.3178571,8.83392857 C19.9178571,8.83392857 20.5875,11.2071429 20.5875,14.2928571 L20.5875,20.5714286 L20.5875,20.5714286 Z" id="path-1"></path>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="icon-linkedin-gray" fill="#6C757D" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" version="1.1" viewBox="0 0 24 24"><title>icon-linkedin-gray</title><defs><path id="path-1" d="M22.2857143,0 L1.70892857,0 C0.766071429,0 0,0.776785714 0,1.73035714 L0,22.2696429 C0,23.2232143 0.766071429,24 1.70892857,24 L22.2857143,24 C23.2285714,24 24,23.2232143 24,22.2696429 L24,1.73035714 C24,0.776785714 23.2285714,0 22.2857143,0 Z M7.25357143,20.5714286 L3.69642857,20.5714286 L3.69642857,9.11785714 L7.25892857,9.11785714 L7.25892857,20.5714286 L7.25357143,20.5714286 Z M5.475,7.55357143 C4.33392857,7.55357143 3.4125,6.62678571 3.4125,5.49107143 C3.4125,4.35535714 4.33392857,3.42857143 5.475,3.42857143 C6.61071429,3.42857143 7.5375,4.35535714 7.5375,5.49107143 C7.5375,6.63214286 6.61607143,7.55357143 5.475,7.55357143 L5.475,7.55357143 Z M20.5875,20.5714286 L17.0303571,20.5714286 L17.0303571,15 C17.0303571,13.6714286 17.0035714,11.9625 15.1821429,11.9625 C13.3285714,11.9625 13.0446429,13.4089286 13.0446429,14.9035714 L13.0446429,20.5714286 L9.4875,20.5714286 L9.4875,9.11785714 L12.9,9.11785714 L12.9,10.6821429 L12.9482143,10.6821429 C13.425,9.78214286 14.5875,8.83392857 16.3178571,8.83392857 C19.9178571,8.83392857 20.5875,11.2071429 20.5875,14.2928571 L20.5875,20.5714286 L20.5875,20.5714286 Z"/></defs><g id="Page-1" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><mask id="mask-2" fill="#fff"><use xlink:href="#path-1"/></mask><use id="icon-linkedin-gray" fill="#6C757D" fill-rule="nonzero" xlink:href="#path-1"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,15 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon-linkedin-gray</title>
<defs>
<path d="M5.37214286,24 L0.396428571,24 L0.396428571,7.97642802 L5.37214286,7.97642802 L5.37214286,24 Z M2.88160714,5.79066494 C1.29053571,5.79066494 0,4.47277838 0,2.88167143 C0,1.29016824 1.29013948,0 2.88160714,0 C4.47307481,0 5.76321429,1.29016824 5.76321429,2.88167143 C5.76321429,4.47277838 4.47214286,5.79066494 2.88160714,5.79066494 Z M23.9946429,24 L19.0296429,24 L19.0296429,16.1998259 C19.0296429,14.3408558 18.9921429,11.956874 16.4426786,11.956874 C13.8557143,11.956874 13.4592857,13.976562 13.4592857,16.0658943 L13.4592857,24 L8.48892857,24 L8.48892857,7.97642802 L13.2610714,7.97642802 L13.2610714,10.1621911 L13.3307143,10.1621911 C13.995,8.90323442 15.6176786,7.57463333 18.0385714,7.57463333 C23.0742857,7.57463333 24,10.8907788 24,15.1980178 L24,24 L23.9946429,24 Z" id="path-1"></path>
</defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Logo">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Brands/linkedin-in" fill="#6C757D" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" version="1.1" viewBox="0 0 24 24"><title>icon-linkedin-gray</title><defs><path id="path-1" d="M5.37214286,24 L0.396428571,24 L0.396428571,7.97642802 L5.37214286,7.97642802 L5.37214286,24 Z M2.88160714,5.79066494 C1.29053571,5.79066494 0,4.47277838 0,2.88167143 C0,1.29016824 1.29013948,0 2.88160714,0 C4.47307481,0 5.76321429,1.29016824 5.76321429,2.88167143 C5.76321429,4.47277838 4.47214286,5.79066494 2.88160714,5.79066494 Z M23.9946429,24 L19.0296429,24 L19.0296429,16.1998259 C19.0296429,14.3408558 18.9921429,11.956874 16.4426786,11.956874 C13.8557143,11.956874 13.4592857,13.976562 13.4592857,16.0658943 L13.4592857,24 L8.48892857,24 L8.48892857,7.97642802 L13.2610714,7.97642802 L13.2610714,10.1621911 L13.3307143,10.1621911 C13.995,8.90323442 15.6176786,7.57463333 18.0385714,7.57463333 C23.0742857,7.57463333 24,10.8907788 24,15.1980178 L24,24 L23.9946429,24 Z"/></defs><g id="Symbols" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="Logo"><mask id="mask-2" fill="#fff"><use xlink:href="#path-1"/></mask><use id="Brands/linkedin-in" fill="#6C757D" fill-rule="nonzero" xlink:href="#path-1"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -1,10 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="21px" viewBox="0 0 24 21" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group" fill="#495057">
<rect id="Rectangle" x="0" y="0" width="24" height="3"></rect>
<rect id="Rectangle" x="0" y="9" width="24" height="3"></rect>
<rect id="Rectangle" x="0" y="18" width="24" height="3"></rect>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="21" version="1.1" viewBox="0 0 24 21"><g id="Page-1" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="Group" fill="#495057"><rect id="Rectangle" width="24" height="3" x="0" y="0"/><rect id="Rectangle" width="24" height="3" x="0" y="9"/><rect id="Rectangle" width="24" height="3" x="0" y="18"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 560 B

After

Width:  |  Height:  |  Size: 430 B

View File

@ -1,16 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="80px" height="80px" viewBox="0 0 80 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon-performance</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Homepage" transform="translate(-185.000000, -1263.000000)" fill-rule="nonzero">
<g id="Page/Why" transform="translate(185.000000, 1047.000000)">
<g id="Feature-1" transform="translate(0.000000, 216.000000)">
<g id="icon-performance" transform="translate(0.000000, 0.000000)">
<circle id="Oval" fill="#F1F6F9" cx="40" cy="40" r="40"></circle>
<path d="M35.2021333,19.2 C34.8261333,19.2 34.4621333,19.3328 34.1741333,19.5745333 C33.8861333,19.8161333 33.6924,20.1516 33.6270667,20.5218667 L28.8584,41.1718667 L28.8614667,41.1750667 C28.8226667,41.3133333 28.8026667,41.4564 28.8021333,41.6 C28.8021333,42.0244 28.9706667,42.4313333 29.2706667,42.7314667 C29.5708,43.0314667 29.9777333,43.2 30.4021333,43.2 L39.2021333,43.2 L36.8333333,58.8813333 C36.8122667,58.9862667 36.8018667,59.0930667 36.8021333,59.2 C36.8021333,59.6244 36.9706667,60.0313333 37.2706667,60.3314667 C37.5708,60.6314667 37.9777333,60.8 38.4021333,60.8 C38.6928,60.8 38.978,60.7198667 39.2268,60.5696 C39.4756,60.4193333 39.6789333,60.204 39.8145333,59.9469333 L39.8177333,59.9469333 L50.8926667,39.3437333 L50.8770667,39.3156 C51.0665333,39.0528 51.2021333,38.7485333 51.2021333,38.4 C51.2021333,37.5168 50.4853333,36.8 49.6021333,36.8 L40.8021333,36.8 L46.2614667,21.4562667 C46.3542667,21.25 46.4021333,21.0262667 46.4021333,20.8 C46.4021333,20.3757333 46.2334667,19.9686667 45.9334667,19.6686667 C45.6333333,19.3686667 45.2264,19.2 44.8021333,19.2 L35.2021333,19.2 Z" id="Path" fill="#257AF4"></path>
</g>
</g>
</g>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="80" height="80" version="1.1" viewBox="0 0 80 80"><title>icon-performance</title><g id="Page-1" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="Homepage" fill-rule="nonzero" transform="translate(-185.000000, -1263.000000)"><g id="Page/Why" transform="translate(185.000000, 1047.000000)"><g id="Feature-1" transform="translate(0.000000, 216.000000)"><g id="icon-performance" transform="translate(0.000000, 0.000000)"><circle id="Oval" cx="40" cy="40" r="40" fill="#F1F6F9"/><path id="Path" fill="#257AF4" d="M35.2021333,19.2 C34.8261333,19.2 34.4621333,19.3328 34.1741333,19.5745333 C33.8861333,19.8161333 33.6924,20.1516 33.6270667,20.5218667 L28.8584,41.1718667 L28.8614667,41.1750667 C28.8226667,41.3133333 28.8026667,41.4564 28.8021333,41.6 C28.8021333,42.0244 28.9706667,42.4313333 29.2706667,42.7314667 C29.5708,43.0314667 29.9777333,43.2 30.4021333,43.2 L39.2021333,43.2 L36.8333333,58.8813333 C36.8122667,58.9862667 36.8018667,59.0930667 36.8021333,59.2 C36.8021333,59.6244 36.9706667,60.0313333 37.2706667,60.3314667 C37.5708,60.6314667 37.9777333,60.8 38.4021333,60.8 C38.6928,60.8 38.978,60.7198667 39.2268,60.5696 C39.4756,60.4193333 39.6789333,60.204 39.8145333,59.9469333 L39.8177333,59.9469333 L50.8926667,39.3437333 L50.8770667,39.3156 C51.0665333,39.0528 51.2021333,38.7485333 51.2021333,38.4 C51.2021333,37.5168 50.4853333,36.8 49.6021333,36.8 L40.8021333,36.8 L46.2614667,21.4562667 C46.3542667,21.25 46.4021333,21.0262667 46.4021333,20.8 C46.4021333,20.3757333 46.2334667,19.9686667 45.9334667,19.6686667 C45.6333333,19.3686667 45.2264,19.2 44.8021333,19.2 L35.2021333,19.2 Z"/></g></g></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1,16 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="80px" height="80px" viewBox="0 0 80 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon-reliability</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Homepage" transform="translate(-185.000000, -1674.000000)">
<g id="Page/Why" transform="translate(185.000000, 1047.000000)">
<g id="Feature-3" transform="translate(0.000000, 627.000000)">
<g id="icon-reliability" transform="translate(0.000000, 0.000000)">
<circle id="Oval" fill="#F1F6F9" fill-rule="nonzero" cx="40" cy="40" r="40"></circle>
<path d="M39.8666667,62.2222222 C39.8666667,62.2222222 57.6444444,53.3333333 57.6444444,40 L57.6444444,24.4444444 L39.8666667,17.7777778 L22.0888889,24.4444444 L22.0888889,40 C22.0888889,53.3333333 39.8666667,62.2222222 39.8666667,62.2222222 Z" id="Path" stroke="#257AF4" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"></path>
</g>
</g>
</g>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="80" height="80" version="1.1" viewBox="0 0 80 80"><title>icon-reliability</title><g id="Page-1" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="Homepage" transform="translate(-185.000000, -1674.000000)"><g id="Page/Why" transform="translate(185.000000, 1047.000000)"><g id="Feature-3" transform="translate(0.000000, 627.000000)"><g id="icon-reliability" transform="translate(0.000000, 0.000000)"><circle id="Oval" cx="40" cy="40" r="40" fill="#F1F6F9" fill-rule="nonzero"/><path id="Path" stroke="#257AF4" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M39.8666667,62.2222222 C39.8666667,62.2222222 57.6444444,53.3333333 57.6444444,40 L57.6444444,24.4444444 L39.8666667,17.7777778 L22.0888889,24.4444444 L22.0888889,40 C22.0888889,53.3333333 39.8666667,62.2222222 39.8666667,62.2222222 Z"/></g></g></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 948 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -1,16 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="80px" height="80px" viewBox="0 0 80 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon-security</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Homepage" transform="translate(-741.000000, -1674.000000)" fill-rule="nonzero">
<g id="Page/Why" transform="translate(185.000000, 1047.000000)">
<g id="Feature-4" transform="translate(556.000000, 627.000000)">
<g id="icon-security" transform="translate(0.000000, 0.000000)">
<circle id="Oval" fill="#F1F6F9" cx="40" cy="40" r="40"></circle>
<path d="M24,24 C21.794,24 20,25.794 20,28 L20,52 C20,54.206 21.794,56 24,56 C24,57.104 24.896,58 26,58 C27.104,58 28,57.104 28,56 L52,56 C52,57.104 52.896,58 54,58 C55.104,58 56,57.104 56,56 C58.206,56 60,54.206 60,52 L60,28 C60,25.794 58.206,24 56,24 L24,24 Z M53.1757333,30.8281333 C53.6877333,30.8281333 54.1998667,31.0201333 54.5898667,31.4101333 C55.3718667,32.1921333 55.3698667,33.4582667 54.5898667,34.2382667 L52.8672,35.9609333 C53.5712,37.1529333 54,38.52 54,40 C54,41.48 53.5712,42.8490667 52.8672,44.0390667 L54.7656,45.9374667 C55.5456,46.7174667 55.5456,47.9856 54.7656,48.7656 C53.9856,49.5476 52.7194667,49.5456 51.9374667,48.7656 L50.0390667,46.8672 C48.8490667,47.5692 47.48,48 46,48 C44.52,48 43.1509333,47.5712 41.9609333,46.8672 L40.2382667,48.5898667 C39.4582667,49.3698667 38.1901333,49.3698667 37.4101333,48.5898667 C36.6301333,47.8098667 36.6301333,46.5417333 37.4101333,45.7617333 L39.1328,44.0390667 C38.4288,42.8490667 38,41.48 38,40 C38,38.52 38.4288,37.1509333 39.1328,35.9609333 L37.5898667,34.414 C36.8098667,33.634 36.8098667,32.3698667 37.5898667,31.5898667 C38.3698667,30.8098667 39.634,30.8098667 40.414,31.5898667 L41.9609333,33.1328 C43.1509333,32.4288 44.52,32 46,32 C47.48,32 48.8490667,32.4288 50.0390667,33.1328 L51.7617333,31.4101333 C52.1517333,31.0201333 52.6637333,30.8281333 53.1757333,30.8281333 Z M28,34 C29.104,34 30,34.896 30,36 L30,44 C30,45.104 29.104,46 28,46 C26.896,46 26,45.104 26,44 L26,36 C26,34.896 26.896,34 28,34 Z M46,36 C44.9392,36 43.9217333,36.4214667 43.1716,37.1716 C42.4214667,37.9217333 42,38.9392 42,40 C42,41.0608 42.4214667,42.0782667 43.1716,42.8284 C43.9217333,43.5785333 44.9392,44 46,44 C47.0608,44 48.0782667,43.5785333 48.8284,42.8284 C49.5785333,42.0782667 50,41.0608 50,40 C50,38.9392 49.5785333,37.9217333 48.8284,37.1716 C48.0782667,36.4214667 47.0608,36 46,36 Z" id="Shape" fill="#257AF4"></path>
</g>
</g>
</g>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="80" height="80" version="1.1" viewBox="0 0 80 80"><title>icon-security</title><g id="Page-1" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="Homepage" fill-rule="nonzero" transform="translate(-741.000000, -1674.000000)"><g id="Page/Why" transform="translate(185.000000, 1047.000000)"><g id="Feature-4" transform="translate(556.000000, 627.000000)"><g id="icon-security" transform="translate(0.000000, 0.000000)"><circle id="Oval" cx="40" cy="40" r="40" fill="#F1F6F9"/><path id="Shape" fill="#257AF4" d="M24,24 C21.794,24 20,25.794 20,28 L20,52 C20,54.206 21.794,56 24,56 C24,57.104 24.896,58 26,58 C27.104,58 28,57.104 28,56 L52,56 C52,57.104 52.896,58 54,58 C55.104,58 56,57.104 56,56 C58.206,56 60,54.206 60,52 L60,28 C60,25.794 58.206,24 56,24 L24,24 Z M53.1757333,30.8281333 C53.6877333,30.8281333 54.1998667,31.0201333 54.5898667,31.4101333 C55.3718667,32.1921333 55.3698667,33.4582667 54.5898667,34.2382667 L52.8672,35.9609333 C53.5712,37.1529333 54,38.52 54,40 C54,41.48 53.5712,42.8490667 52.8672,44.0390667 L54.7656,45.9374667 C55.5456,46.7174667 55.5456,47.9856 54.7656,48.7656 C53.9856,49.5476 52.7194667,49.5456 51.9374667,48.7656 L50.0390667,46.8672 C48.8490667,47.5692 47.48,48 46,48 C44.52,48 43.1509333,47.5712 41.9609333,46.8672 L40.2382667,48.5898667 C39.4582667,49.3698667 38.1901333,49.3698667 37.4101333,48.5898667 C36.6301333,47.8098667 36.6301333,46.5417333 37.4101333,45.7617333 L39.1328,44.0390667 C38.4288,42.8490667 38,41.48 38,40 C38,38.52 38.4288,37.1509333 39.1328,35.9609333 L37.5898667,34.414 C36.8098667,33.634 36.8098667,32.3698667 37.5898667,31.5898667 C38.3698667,30.8098667 39.634,30.8098667 40.414,31.5898667 L41.9609333,33.1328 C43.1509333,32.4288 44.52,32 46,32 C47.48,32 48.8490667,32.4288 50.0390667,33.1328 L51.7617333,31.4101333 C52.1517333,31.0201333 52.6637333,30.8281333 53.1757333,30.8281333 Z M28,34 C29.104,34 30,34.896 30,36 L30,44 C30,45.104 29.104,46 28,46 C26.896,46 26,45.104 26,44 L26,36 C26,34.896 26.896,34 28,34 Z M46,36 C44.9392,36 43.9217333,36.4214667 43.1716,37.1716 C42.4214667,37.9217333 42,38.9392 42,40 C42,41.0608 42.4214667,42.0782667 43.1716,42.8284 C43.9217333,43.5785333 44.9392,44 46,44 C47.0608,44 48.0782667,43.5785333 48.8284,42.8284 C49.5785333,42.0782667 50,41.0608 50,40 C50,38.9392 49.5785333,37.9217333 48.8284,37.1716 C48.0782667,36.4214667 47.0608,36 46,36 Z"/></g></g></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -1,14 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon-slack</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Link/Slack" fill="#212529" fill-rule="nonzero">
<g id="Icon/Slack">
<path d="M5.13302911,0 C4.35912849,0.000570846075 3.73280093,0.627359837 3.73337253,1.39971458 C3.73280093,2.17206932 4.35970047,2.79885831 5.13360109,2.79942915 L6.53382966,2.79942915 L6.53382966,1.40028542 C6.53440125,0.627930683 5.90750171,0.00114169215 5.13302911,0 C5.13360109,0 5.13360109,0 5.13302911,0 M5.13302911,3.73333333 L1.40023129,3.73333333 C0.626330674,3.73390418 -0.000568866549,4.36069317 1.55890848e-06,5.13304791 C-0.00114085518,5.90540265 0.625758685,6.53219164 1.3996593,6.53333333 L5.13302911,6.53333333 C5.90692972,6.53276249 6.53382926,5.9059735 6.53325767,5.13361876 C6.53382926,4.36069317 5.90692972,3.73390418 5.13302911,3.73333333 Z" id="Shape"></path>
<path d="M13.9999973,5.13304791 C14.0005689,4.36069317 13.3736693,3.73390418 12.5997687,3.73333333 C11.8258681,3.73390418 11.1989685,4.36069317 11.1995401,5.13304791 L11.1995401,6.53333333 L12.5997687,6.53333333 C13.3736693,6.53276249 14.0005689,5.9059735 13.9999973,5.13304791 Z M10.2666275,5.13304791 L10.2666275,1.39971458 C10.2671991,0.627930683 9.64087151,0.00114169215 8.86697089,0 C8.09307028,0.000570846075 7.46617074,0.627359837 7.46674116,1.39971458 L7.46674116,5.13304791 C7.46559875,5.90540265 8.09249829,6.53219164 8.86639891,6.53333333 C9.64029953,6.53276249 10.2671991,5.9059735 10.2666275,5.13304791 L10.2666275,5.13304791 Z" id="Shape"></path>
<path d="M8.86639891,14 C9.64029953,13.9994292 10.2671991,13.3726402 10.2666275,12.6002854 C10.2671991,11.8279307 9.64029953,11.2011417 8.86639891,11.2005708 L7.46617034,11.2005708 L7.46617034,12.6002854 C7.46559875,13.3720693 8.09249829,13.9988583 8.86639891,14 Z M8.86639891,10.2660958 L12.5997687,10.2660958 C13.3736693,10.265525 14.0005689,9.63873598 13.9999984,8.86638124 C14.0011409,8.0940265 13.3742413,7.46723751 12.6003407,7.46609582 L8.86697089,7.46609582 C8.09307028,7.46666667 7.46617074,8.09345566 7.46674233,8.8658104 C7.46617074,9.63873598 8.09249829,10.265525 8.86639891,10.2660958 L8.86639891,10.2660958 Z" id="Shape"></path>
<path d="M2.73097794e-06,8.86638124 C-0.00056886655,9.63873598 0.626330674,10.265525 1.40023129,10.2660958 C2.17413191,10.265525 2.80103145,9.63873598 2.80045986,8.86638124 L2.80045986,7.46666667 L1.40023129,7.46666667 C0.626330674,7.46723751 -0.00056886655,8.0940265 2.73097794e-06,8.86638124 Z M3.73337136,8.86638124 L3.73337136,12.5997146 C3.73222895,13.3720693 4.35912849,13.9988583 5.13302911,14 C5.90692972,13.9994292 6.53382926,13.3726402 6.53325884,12.6002854 L6.53325884,8.86752294 C6.53440125,8.0951682 5.90750171,7.4683792 5.13360109,7.46723751 C4.35912849,7.46723751 3.73280093,8.0940265 3.73337136,8.86638124 C3.73337136,8.86638124 3.73337136,8.86695209 3.73337136,8.86638124" id="Shape"></path>
</g>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="14" version="1.1" viewBox="0 0 14 14"><title>icon-slack</title><g id="Page-1" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="Link/Slack" fill="#212529" fill-rule="nonzero"><g id="Icon/Slack"><path id="Shape" d="M5.13302911,0 C4.35912849,0.000570846075 3.73280093,0.627359837 3.73337253,1.39971458 C3.73280093,2.17206932 4.35970047,2.79885831 5.13360109,2.79942915 L6.53382966,2.79942915 L6.53382966,1.40028542 C6.53440125,0.627930683 5.90750171,0.00114169215 5.13302911,0 C5.13360109,0 5.13360109,0 5.13302911,0 M5.13302911,3.73333333 L1.40023129,3.73333333 C0.626330674,3.73390418 -0.000568866549,4.36069317 1.55890848e-06,5.13304791 C-0.00114085518,5.90540265 0.625758685,6.53219164 1.3996593,6.53333333 L5.13302911,6.53333333 C5.90692972,6.53276249 6.53382926,5.9059735 6.53325767,5.13361876 C6.53382926,4.36069317 5.90692972,3.73390418 5.13302911,3.73333333 Z"/><path id="Shape" d="M13.9999973,5.13304791 C14.0005689,4.36069317 13.3736693,3.73390418 12.5997687,3.73333333 C11.8258681,3.73390418 11.1989685,4.36069317 11.1995401,5.13304791 L11.1995401,6.53333333 L12.5997687,6.53333333 C13.3736693,6.53276249 14.0005689,5.9059735 13.9999973,5.13304791 Z M10.2666275,5.13304791 L10.2666275,1.39971458 C10.2671991,0.627930683 9.64087151,0.00114169215 8.86697089,0 C8.09307028,0.000570846075 7.46617074,0.627359837 7.46674116,1.39971458 L7.46674116,5.13304791 C7.46559875,5.90540265 8.09249829,6.53219164 8.86639891,6.53333333 C9.64029953,6.53276249 10.2671991,5.9059735 10.2666275,5.13304791 L10.2666275,5.13304791 Z"/><path id="Shape" d="M8.86639891,14 C9.64029953,13.9994292 10.2671991,13.3726402 10.2666275,12.6002854 C10.2671991,11.8279307 9.64029953,11.2011417 8.86639891,11.2005708 L7.46617034,11.2005708 L7.46617034,12.6002854 C7.46559875,13.3720693 8.09249829,13.9988583 8.86639891,14 Z M8.86639891,10.2660958 L12.5997687,10.2660958 C13.3736693,10.265525 14.0005689,9.63873598 13.9999984,8.86638124 C14.0011409,8.0940265 13.3742413,7.46723751 12.6003407,7.46609582 L8.86697089,7.46609582 C8.09307028,7.46666667 7.46617074,8.09345566 7.46674233,8.8658104 C7.46617074,9.63873598 8.09249829,10.265525 8.86639891,10.2660958 L8.86639891,10.2660958 Z"/><path id="Shape" d="M2.73097794e-06,8.86638124 C-0.00056886655,9.63873598 0.626330674,10.265525 1.40023129,10.2660958 C2.17413191,10.265525 2.80103145,9.63873598 2.80045986,8.86638124 L2.80045986,7.46666667 L1.40023129,7.46666667 C0.626330674,7.46723751 -0.00056886655,8.0940265 2.73097794e-06,8.86638124 Z M3.73337136,8.86638124 L3.73337136,12.5997146 C3.73222895,13.3720693 4.35912849,13.9988583 5.13302911,14 C5.90692972,13.9994292 6.53382926,13.3726402 6.53325884,12.6002854 L6.53325884,8.86752294 C6.53440125,8.0951682 5.90750171,7.4683792 5.13360109,7.46723751 C4.35912849,7.46723751 3.73280093,8.0940265 3.73337136,8.86638124 C3.73337136,8.86638124 3.73337136,8.86695209 3.73337136,8.86638124"/></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -1,12 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="80px" height="80px" viewBox="0 0 80 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon-slack</title>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon-slack" fill-rule="nonzero">
<path d="M29.3315949,0 C24.9093056,0.00326197757 21.3302911,3.58491335 21.3335573,7.99836901 C21.3302911,12.4118247 24.9125741,15.993476 29.3348634,15.996738 L37.3361695,15.996738 L37.3361695,8.00163099 C37.3394357,3.58817533 33.7571526,0.00652395515 29.3315949,0 C29.3348634,0 29.3348634,0 29.3315949,0 M29.3315949,21.3333333 L8.00132167,21.3333333 C3.57903242,21.3365953 -0.003250666,24.9182467 8.9080479e-06,29.3317023 C-0.00651917247,33.745158 3.57576392,37.3268094 7.99805317,37.3333333 L29.3315949,37.3333333 C33.7538841,37.3300714 37.3361672,33.74842 37.332901,29.3349643 C37.3361672,24.9182467 33.7538841,21.3365953 29.3315949,21.3333333 Z" id="Shape" fill="#36C5F0"></path>
<path d="M79.9999844,29.3317023 C80.0032507,24.9182467 76.4209676,21.3365953 71.9986783,21.3333333 C67.5763891,21.3365953 63.994106,24.9182467 63.9973723,29.3317023 L63.9973723,37.3333333 L71.9986783,37.3333333 C76.4209676,37.3300714 80.0032507,33.74842 79.9999844,29.3317023 Z M58.6664427,29.3317023 L58.6664427,7.99836901 C58.6697089,3.58817533 55.0906944,0.00652395515 50.6684051,0 C46.2461159,0.00326197757 42.6638328,3.58491335 42.6670923,7.99836901 L42.6670923,29.3317023 C42.6605643,33.745158 46.2428474,37.3268094 50.6651366,37.3333333 C55.0874259,37.3300714 58.6697089,33.74842 58.6664427,29.3317023 L58.6664427,29.3317023 Z" id="Shape" fill="#2EB67D"></path>
<path d="M50.6651366,80 C55.0874259,79.996738 58.6697089,76.4150866 58.6664427,72.001631 C58.6697089,67.5881753 55.0874259,64.006524 50.6651366,64.003262 L42.6638305,64.003262 L42.6638305,72.001631 C42.6605643,76.4118247 46.2428474,79.993476 50.6651366,80 Z M50.6651366,58.6634047 L71.9986783,58.6634047 C76.4209676,58.6601427 80.0032507,55.0784913 79.9999911,50.6650357 C80.0065192,46.25158 76.4242361,42.6699286 72.0019468,42.6634047 L50.6684051,42.6634047 C46.2461159,42.6666667 42.6638328,46.248318 42.667099,50.6617737 C42.6638328,55.0784913 46.2428474,58.6601427 50.6651366,58.6634047 L50.6651366,58.6634047 Z" id="Shape" fill="#ECB22E"></path>
<path d="M1.56055896e-05,50.6650357 C-0.003250666,55.0784913 3.57903242,58.6601427 8.00132167,58.6634047 C12.4236109,58.6601427 16.005894,55.0784913 16.0026277,50.6650357 L16.0026277,42.6666667 L8.00132167,42.6666667 C3.57903242,42.6699286 -0.003250666,46.25158 1.56055896e-05,50.6650357 Z M21.3335506,50.6650357 L21.3335506,71.998369 C21.3270225,76.4118247 24.9093056,79.993476 29.3315949,80 C33.7538841,79.996738 37.3361672,76.4150866 37.3329077,72.001631 L37.3329077,50.6715596 C37.3394357,46.258104 33.7571526,42.6764526 29.3348634,42.6699286 C24.9093056,42.6699286 21.3302911,46.25158 21.3335506,50.6650357 C21.3335506,50.6650357 21.3335506,50.6682977 21.3335506,50.6650357" id="Shape" fill="#E01E5A"></path>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="80" height="80" version="1.1" viewBox="0 0 80 80"><title>icon-slack</title><g id="Symbols" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="icon-slack" fill-rule="nonzero"><path id="Shape" fill="#36C5F0" d="M29.3315949,0 C24.9093056,0.00326197757 21.3302911,3.58491335 21.3335573,7.99836901 C21.3302911,12.4118247 24.9125741,15.993476 29.3348634,15.996738 L37.3361695,15.996738 L37.3361695,8.00163099 C37.3394357,3.58817533 33.7571526,0.00652395515 29.3315949,0 C29.3348634,0 29.3348634,0 29.3315949,0 M29.3315949,21.3333333 L8.00132167,21.3333333 C3.57903242,21.3365953 -0.003250666,24.9182467 8.9080479e-06,29.3317023 C-0.00651917247,33.745158 3.57576392,37.3268094 7.99805317,37.3333333 L29.3315949,37.3333333 C33.7538841,37.3300714 37.3361672,33.74842 37.332901,29.3349643 C37.3361672,24.9182467 33.7538841,21.3365953 29.3315949,21.3333333 Z"/><path id="Shape" fill="#2EB67D" d="M79.9999844,29.3317023 C80.0032507,24.9182467 76.4209676,21.3365953 71.9986783,21.3333333 C67.5763891,21.3365953 63.994106,24.9182467 63.9973723,29.3317023 L63.9973723,37.3333333 L71.9986783,37.3333333 C76.4209676,37.3300714 80.0032507,33.74842 79.9999844,29.3317023 Z M58.6664427,29.3317023 L58.6664427,7.99836901 C58.6697089,3.58817533 55.0906944,0.00652395515 50.6684051,0 C46.2461159,0.00326197757 42.6638328,3.58491335 42.6670923,7.99836901 L42.6670923,29.3317023 C42.6605643,33.745158 46.2428474,37.3268094 50.6651366,37.3333333 C55.0874259,37.3300714 58.6697089,33.74842 58.6664427,29.3317023 L58.6664427,29.3317023 Z"/><path id="Shape" fill="#ECB22E" d="M50.6651366,80 C55.0874259,79.996738 58.6697089,76.4150866 58.6664427,72.001631 C58.6697089,67.5881753 55.0874259,64.006524 50.6651366,64.003262 L42.6638305,64.003262 L42.6638305,72.001631 C42.6605643,76.4118247 46.2428474,79.993476 50.6651366,80 Z M50.6651366,58.6634047 L71.9986783,58.6634047 C76.4209676,58.6601427 80.0032507,55.0784913 79.9999911,50.6650357 C80.0065192,46.25158 76.4242361,42.6699286 72.0019468,42.6634047 L50.6684051,42.6634047 C46.2461159,42.6666667 42.6638328,46.248318 42.667099,50.6617737 C42.6638328,55.0784913 46.2428474,58.6601427 50.6651366,58.6634047 L50.6651366,58.6634047 Z"/><path id="Shape" fill="#E01E5A" d="M1.56055896e-05,50.6650357 C-0.003250666,55.0784913 3.57903242,58.6601427 8.00132167,58.6634047 C12.4236109,58.6601427 16.005894,55.0784913 16.0026277,50.6650357 L16.0026277,42.6666667 L8.00132167,42.6666667 C3.57903242,42.6699286 -0.003250666,46.25158 1.56055896e-05,50.6650357 Z M21.3335506,50.6650357 L21.3335506,71.998369 C21.3270225,76.4118247 24.9093056,79.993476 29.3315949,80 C33.7538841,79.996738 37.3361672,76.4150866 37.3329077,72.001631 L37.3329077,50.6715596 C37.3394357,46.258104 33.7571526,42.6764526 29.3348634,42.6699286 C24.9093056,42.6699286 21.3302911,46.25158 21.3335506,50.6650357 C21.3335506,50.6650357 21.3335506,50.6682977 21.3335506,50.6650357"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -1,16 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="64px" height="80px" viewBox="0 0 64 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon-stack-overflow</title>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon-stack-overflow" fill-rule="nonzero">
<polygon id="Path" fill="#607D8B" points="0 47.5675676 6.39914678 47.5675676 6.39914678 77.8378378 0 77.8378378"></polygon>
<polygon id="Path" fill="#607D8B" points="0 73.5135135 55.4592721 73.5135135 55.4592721 80 0 80"></polygon>
<path d="M49.0601253,47.5675676 L55.4592721,47.5675676 L55.4592721,77.8378378 L49.0601253,77.8378378 L49.0601253,47.5675676 Z M12.7982936,60.5405405 L42.6609785,60.5405405 L42.6609785,67.027027 L12.7982936,67.027027 L12.7982936,60.5405405 Z" id="Shape" fill="#607D8B"></path>
<polygon id="Path" fill="#A68A6E" points="12.9732036 48.1292973 42.6646047 51.368 41.979896 57.8170811 12.2887082 54.5783784"></polygon>
<polygon id="Path" fill="#EF6C00" points="59.4493534 0 64 29.9145946 57.6735902 30.9033514 53.1229436 0.988864865"></polygon>
<polygon id="Path" fill="#FF9800" points="41.5279029 4.83636757 56.0989735 31.2536216 50.5118784 34.4201081 35.9405946 8.0028973"></polygon>
<polygon id="Path" fill="#D38B28" points="24.5300627 18.4892973 49.0586322 35.7472432 45.4085589 41.0776216 20.8799893 23.8196757"></polygon>
<polygon id="Path" fill="#C09553" points="16.8498067 32.9033514 44.947607 43.1487568 42.7808559 49.2544865 14.6830556 39.0088649"></polygon>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="80" version="1.1" viewBox="0 0 64 80"><title>icon-stack-overflow</title><g id="Symbols" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="icon-stack-overflow" fill-rule="nonzero"><polygon id="Path" fill="#607D8B" points="0 47.568 6.399 47.568 6.399 77.838 0 77.838"/><polygon id="Path" fill="#607D8B" points="0 73.514 55.459 73.514 55.459 80 0 80"/><path id="Shape" fill="#607D8B" d="M49.0601253,47.5675676 L55.4592721,47.5675676 L55.4592721,77.8378378 L49.0601253,77.8378378 L49.0601253,47.5675676 Z M12.7982936,60.5405405 L42.6609785,60.5405405 L42.6609785,67.027027 L12.7982936,67.027027 L12.7982936,60.5405405 Z"/><polygon id="Path" fill="#A68A6E" points="12.973 48.129 42.665 51.368 41.98 57.817 12.289 54.578"/><polygon id="Path" fill="#EF6C00" points="59.449 0 64 29.915 57.674 30.903 53.123 .989"/><polygon id="Path" fill="#FF9800" points="41.528 4.836 56.099 31.254 50.512 34.42 35.941 8.003"/><polygon id="Path" fill="#D38B28" points="24.53 18.489 49.059 35.747 45.409 41.078 20.88 23.82"/><polygon id="Path" fill="#C09553" points="16.85 32.903 44.948 43.149 42.781 49.254 14.683 39.009"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1,12 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="80px" height="80px" viewBox="0 0 80 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon-telegram</title>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon-telegram" fill-rule="nonzero">
<path d="M40,0 C29.3914,0 19.2172,4.21428 11.71572,11.71572 C4.21428,19.2172 0,29.3914 0,40 C0,50.6086 4.21428,60.7828 11.71572,68.2842 C19.2172,75.7858 29.3914,80 40,80 C50.6086,80 60.7828,75.7858 68.2842,68.2842 C75.7858,60.7828 80,50.6086 80,40 C80,29.3914 75.7858,19.2172 68.2842,11.71572 C60.7828,4.21428 50.6086,0 40,0 Z" id="Path" fill="#29B6F6"></path>
<path d="M59.9,21.9999936 L52.408,60.252 C52.408,60.252 52.086,61.9999936 49.918,61.9999936 C48.766,61.9999936 48.172,61.452 48.172,61.452 L31.944,47.986 L24.004,43.984 L13.814,41.274 C13.814,41.274 12,40.75 12,39.25 C12,37.9999936 13.866,37.404 13.866,37.404 L56.498,20.468 C56.496,20.466 57.8,19.998 58.75,19.9999936 C59.334,19.9999936 60,20.25 60,20.9999936 C60,21.4999936 59.9,21.9999936 59.9,21.9999936 Z" id="Path" fill="#FFFFFF"></path>
<path d="M37.9996,53.01 L31.1476,59.758 C31.1476,59.758 30.8496,59.988 30.4516,59.998 C30.3136,60.002 30.1656,59.98 30.0136,59.912 L31.9416,47.982 L37.9996,53.01 Z" id="Path" fill="#B0BEC5"></path>
<path d="M51.794,28.3918 C51.456,27.9518 50.832,27.8718 50.392,28.2058 L24,43.9998 C24,43.9998 28.212,55.7838 28.854,57.8238 C29.498,59.8658 30.014,59.9138 30.014,59.9138 L31.942,47.9838 L51.606,29.7918 C52.046,29.4578 52.128,28.8318 51.794,28.3918 Z" id="Path" fill="#CFD8DC"></path>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="80" height="80" version="1.1" viewBox="0 0 80 80"><title>icon-telegram</title><g id="Symbols" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="icon-telegram" fill-rule="nonzero"><path id="Path" fill="#29B6F6" d="M40,0 C29.3914,0 19.2172,4.21428 11.71572,11.71572 C4.21428,19.2172 0,29.3914 0,40 C0,50.6086 4.21428,60.7828 11.71572,68.2842 C19.2172,75.7858 29.3914,80 40,80 C50.6086,80 60.7828,75.7858 68.2842,68.2842 C75.7858,60.7828 80,50.6086 80,40 C80,29.3914 75.7858,19.2172 68.2842,11.71572 C60.7828,4.21428 50.6086,0 40,0 Z"/><path id="Path" fill="#FFF" d="M59.9,21.9999936 L52.408,60.252 C52.408,60.252 52.086,61.9999936 49.918,61.9999936 C48.766,61.9999936 48.172,61.452 48.172,61.452 L31.944,47.986 L24.004,43.984 L13.814,41.274 C13.814,41.274 12,40.75 12,39.25 C12,37.9999936 13.866,37.404 13.866,37.404 L56.498,20.468 C56.496,20.466 57.8,19.998 58.75,19.9999936 C59.334,19.9999936 60,20.25 60,20.9999936 C60,21.4999936 59.9,21.9999936 59.9,21.9999936 Z"/><path id="Path" fill="#B0BEC5" d="M37.9996,53.01 L31.1476,59.758 C31.1476,59.758 30.8496,59.988 30.4516,59.998 C30.3136,60.002 30.1656,59.98 30.0136,59.912 L31.9416,47.982 L37.9996,53.01 Z"/><path id="Path" fill="#CFD8DC" d="M51.794,28.3918 C51.456,27.9518 50.832,27.8718 50.392,28.2058 L24,43.9998 C24,43.9998 28.212,55.7838 28.854,57.8238 C29.498,59.8658 30.014,59.9138 30.014,59.9138 L31.942,47.9838 L51.606,29.7918 C52.046,29.4578 52.128,28.8318 51.794,28.3918 Z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,11 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="31px" height="24px" viewBox="0 0 31 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon-twitter-gray</title>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Twitter-Link" fill="#6C757D" fill-rule="nonzero">
<g id="twitter">
<path d="M30.2608696,2.8377931 C29.1488762,3.32275862 27.9528319,3.64634483 26.691228,3.79944828 C27.9738447,3.04965517 28.9606022,1.8537931 29.4237226,0.441103448 C28.2234758,1.1337931 26.8937906,1.64275862 25.4792141,1.91089655 C24.34957,0.731586207 22.7383143,0 20.9530733,0 C17.5237967,0 14.7442335,2.71282759 14.7442335,6.05793103 C14.7442335,6.53131034 14.8005476,6.99227586 14.9064518,7.44 C9.74740771,7.18510345 5.17167689,4.7702069 2.11051802,1.10565517 C1.57259228,2.00110345 1.27000905,3.04965517 1.27000905,4.15613793 C1.27000905,6.25903448 2.36351122,8.11034483 4.03110622,9.20110345 C3.01322465,9.17048276 2.05504443,8.89158621 1.21621648,8.44468966 C1.21621648,8.46289655 1.21621648,8.4902069 1.21621648,8.51586207 C1.21621648,11.4546207 3.35699282,13.9017931 6.1945763,14.4587586 C5.67598227,14.5986207 5.12797042,14.6764138 4.5631484,14.6764138 C4.16222562,14.6764138 3.77138895,14.6317241 3.39315992,14.5646897 C4.18323835,16.9663448 6.4753063,18.7216552 9.19099077,18.7737931 C7.0661841,20.3958621 4.39000355,21.3674483 1.48013629,21.3674483 C0.977511929,21.3674483 0.485814183,21.3393103 -7.46521926e-16,21.2813793 C2.74930483,22.9953103 6.01386688,24 9.51794876,24 C20.9362631,24 27.1829257,14.7674483 27.1829257,6.75806897 C27.1829257,6.49572414 27.1745206,6.2342069 27.161913,5.976 C28.380651,5.12855172 29.4312872,4.05931034 30.2608696,2.8377931 Z" id="Path"></path>
</g>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="31" height="24" version="1.1" viewBox="0 0 31 24"><title>icon-twitter-gray</title><g id="Symbols" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="Twitter-Link" fill="#6C757D" fill-rule="nonzero"><g id="twitter"><path id="Path" d="M30.2608696,2.8377931 C29.1488762,3.32275862 27.9528319,3.64634483 26.691228,3.79944828 C27.9738447,3.04965517 28.9606022,1.8537931 29.4237226,0.441103448 C28.2234758,1.1337931 26.8937906,1.64275862 25.4792141,1.91089655 C24.34957,0.731586207 22.7383143,0 20.9530733,0 C17.5237967,0 14.7442335,2.71282759 14.7442335,6.05793103 C14.7442335,6.53131034 14.8005476,6.99227586 14.9064518,7.44 C9.74740771,7.18510345 5.17167689,4.7702069 2.11051802,1.10565517 C1.57259228,2.00110345 1.27000905,3.04965517 1.27000905,4.15613793 C1.27000905,6.25903448 2.36351122,8.11034483 4.03110622,9.20110345 C3.01322465,9.17048276 2.05504443,8.89158621 1.21621648,8.44468966 C1.21621648,8.46289655 1.21621648,8.4902069 1.21621648,8.51586207 C1.21621648,11.4546207 3.35699282,13.9017931 6.1945763,14.4587586 C5.67598227,14.5986207 5.12797042,14.6764138 4.5631484,14.6764138 C4.16222562,14.6764138 3.77138895,14.6317241 3.39315992,14.5646897 C4.18323835,16.9663448 6.4753063,18.7216552 9.19099077,18.7737931 C7.0661841,20.3958621 4.39000355,21.3674483 1.48013629,21.3674483 C0.977511929,21.3674483 0.485814183,21.3393103 -7.46521926e-16,21.2813793 C2.74930483,22.9953103 6.01386688,24 9.51794876,24 C20.9362631,24 27.1829257,14.7674483 27.1829257,6.75806897 C27.1829257,6.49572414 27.1745206,6.2342069 27.161913,5.976 C28.380651,5.12855172 29.4312872,4.05931034 30.2608696,2.8377931 Z"/></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1,16 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 248 204" style="enable-background:new 0 0 248 204;" xml:space="preserve">
<style type="text/css">
.st0{fill:#1D9BF0;}
</style>
<g id="Logo_1_">
<path id="white_background" class="st0" d="M221.95,51.29c0.15,2.17,0.15,4.34,0.15,6.53c0,66.73-50.8,143.69-143.69,143.69v-0.04
C50.97,201.51,24.1,193.65,1,178.83c3.99,0.48,8,0.72,12.02,0.73c22.74,0.02,44.83-7.61,62.72-21.66
c-21.61-0.41-40.56-14.5-47.18-35.07c7.57,1.46,15.37,1.16,22.8-0.87C27.8,117.2,10.85,96.5,10.85,72.46c0-0.22,0-0.43,0-0.64
c7.02,3.91,14.88,6.08,22.92,6.32C11.58,63.31,4.74,33.79,18.14,10.71c25.64,31.55,63.47,50.73,104.08,52.76
c-4.07-17.54,1.49-35.92,14.61-48.25c20.34-19.12,52.33-18.14,71.45,2.19c11.31-2.23,22.15-6.38,32.07-12.26
c-3.77,11.69-11.66,21.62-22.2,27.93c10.01-1.18,19.79-3.86,29-7.95C240.37,35.29,231.83,44.14,221.95,51.29z"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Logo" x="0" y="0" version="1.1" viewBox="0 0 248 204" xml:space="preserve" style="enable-background:new 0 0 248 204"><style type="text/css">.st0{fill:#1d9bf0}</style><g id="Logo_1_"><path id="white_background" d="M221.95,51.29c0.15,2.17,0.15,4.34,0.15,6.53c0,66.73-50.8,143.69-143.69,143.69v-0.04 C50.97,201.51,24.1,193.65,1,178.83c3.99,0.48,8,0.72,12.02,0.73c22.74,0.02,44.83-7.61,62.72-21.66 c-21.61-0.41-40.56-14.5-47.18-35.07c7.57,1.46,15.37,1.16,22.8-0.87C27.8,117.2,10.85,96.5,10.85,72.46c0-0.22,0-0.43,0-0.64 c7.02,3.91,14.88,6.08,22.92,6.32C11.58,63.31,4.74,33.79,18.14,10.71c25.64,31.55,63.47,50.73,104.08,52.76 c-4.07-17.54,1.49-35.92,14.61-48.25c20.34-19.12,52.33-18.14,71.45,2.19c11.31-2.23,22.15-6.38,32.07-12.26 c-3.77,11.69-11.66,21.62-22.2,27.93c10.01-1.18,19.79-3.86,29-7.95C240.37,35.29,231.83,44.14,221.95,51.29z" class="st0"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 943 B

View File

@ -1,15 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="14px" viewBox="0 0 20 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon-youtube</title>
<defs>
<path d="M19.5820806,2.19052604 C19.3520638,1.32828646 18.6743546,0.649213542 17.8138699,0.418760417 C16.2541794,0 10,0 10,0 C10,0 3.74585724,0 2.18613014,0.418760417 C1.32564535,0.64925 0.647936221,1.32828646 0.417919412,2.19052604 C0,3.75338542 0,7.01414583 0,7.01414583 C0,7.01414583 0,10.2749062 0.417919412,11.8377656 C0.647936221,12.7000052 1.32564535,13.3507865 2.18613014,13.5812396 C3.74585724,14 10,14 10,14 C10,14 16.2541428,14 17.8138699,13.5812396 C18.6743546,13.3507865 19.3520638,12.7000052 19.5820806,11.8377656 C20,10.2749062 20,7.01414583 20,7.01414583 C20,7.01414583 20,3.75338542 19.5820806,2.19052604 Z M7.95453131,9.97467188 L7.95453131,4.05361979 L13.1817832,7.01421875 L7.95453131,9.97467188 Z" id="path-1"></path>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icon/Youtube">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Brands/youtube" fill="#212529" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="14" version="1.1" viewBox="0 0 20 14"><title>icon-youtube</title><defs><path id="path-1" d="M19.5820806,2.19052604 C19.3520638,1.32828646 18.6743546,0.649213542 17.8138699,0.418760417 C16.2541794,0 10,0 10,0 C10,0 3.74585724,0 2.18613014,0.418760417 C1.32564535,0.64925 0.647936221,1.32828646 0.417919412,2.19052604 C0,3.75338542 0,7.01414583 0,7.01414583 C0,7.01414583 0,10.2749062 0.417919412,11.8377656 C0.647936221,12.7000052 1.32564535,13.3507865 2.18613014,13.5812396 C3.74585724,14 10,14 10,14 C10,14 16.2541428,14 17.8138699,13.5812396 C18.6743546,13.3507865 19.3520638,12.7000052 19.5820806,11.8377656 C20,10.2749062 20,7.01414583 20,7.01414583 C20,7.01414583 20,3.75338542 19.5820806,2.19052604 Z M7.95453131,9.97467188 L7.95453131,4.05361979 L13.1817832,7.01421875 L7.95453131,9.97467188 Z"/></defs><g id="Page-1" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="Icon/Youtube"><mask id="mask-2" fill="#fff"><use xlink:href="#path-1"/></mask><use id="Brands/youtube" fill="#212529" fill-rule="nonzero" xlink:href="#path-1"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,10 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="80px" height="80px" viewBox="0 0 80 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon-youtube</title>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon-youtube" transform="translate(0.000000, 10.000000)" fill-rule="nonzero">
<path d="M78.2044888,49.8 C77.4064838,54 74.0149626,57.2 69.8254364,57.8 C63.2418953,58.8 52.2693267,60 39.9002494,60 C27.7306733,60 16.7581047,58.8 9.97506234,57.8 C5.78553616,57.2 2.39401496,54 1.59600998,49.8 C0.798004988,45.2 0,38.4 0,30 C0,21.6 0.798004988,14.8 1.59600998,10.2 C2.39401496,6 5.78553616,2.8 9.97506234,2.2 C16.5586035,1.2 27.5311721,0 39.9002494,0 C52.2693267,0 63.042394,1.2 69.8254364,2.2 C74.0149626,2.8 77.4064838,6 78.2044888,10.2 C79.0024938,14.8 80,21.6 80,30 C79.8004988,38.4 79.0024938,45.2 78.2044888,49.8 Z" id="Path" fill="#FF3D00"></path>
<polygon id="Path" fill="#FFFFFF" points="31.9201995 44 31.9201995 16 55.8603491 30"></polygon>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="80" height="80" version="1.1" viewBox="0 0 80 80"><title>icon-youtube</title><g id="Symbols" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="icon-youtube" fill-rule="nonzero" transform="translate(0.000000, 10.000000)"><path id="Path" fill="#FF3D00" d="M78.2044888,49.8 C77.4064838,54 74.0149626,57.2 69.8254364,57.8 C63.2418953,58.8 52.2693267,60 39.9002494,60 C27.7306733,60 16.7581047,58.8 9.97506234,57.8 C5.78553616,57.2 2.39401496,54 1.59600998,49.8 C0.798004988,45.2 0,38.4 0,30 C0,21.6 0.798004988,14.8 1.59600998,10.2 C2.39401496,6 5.78553616,2.8 9.97506234,2.2 C16.5586035,1.2 27.5311721,0 39.9002494,0 C52.2693267,0 63.042394,1.2 69.8254364,2.2 C74.0149626,2.8 77.4064838,6 78.2044888,10.2 C79.0024938,14.8 80,21.6 80,30 C79.8004988,38.4 79.0024938,45.2 78.2044888,49.8 Z"/><polygon id="Path" fill="#FFF" points="31.92 44 31.92 16 55.86 30"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 978 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -1,25 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="1062px" height="155px" viewBox="0 0 1062 155" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>cf-logo-h</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="cf-logo-h" fill-rule="nonzero">
<g id="Group" transform="translate(367.600000, 95.800000)" fill="#404041">
<polygon id="Path" points="77.1 1.1 92.7 1.1 92.7 43.6 119.8 43.6 119.8 57.2 77.1 57.2"></polygon>
<path d="M135.9,29.3 L135.9,29.2 C135.9,13.1 148.9,0 166.2,0 C183.5,0 196.3,12.9 196.3,29 L196.3,29.2 C196.3,45.3 183.3,58.4 166,58.4 C148.8,58.3 135.9,45.4 135.9,29.3 M180.5,29.3 L180.5,29.2 C180.5,21.1 174.7,14.1 166.1,14.1 C157.6,14.1 151.9,21 151.9,29.1 L151.9,29.3 C151.9,37.4 157.7,44.4 166.2,44.4 C174.8,44.3 180.5,37.4 180.5,29.3" id="Shape"></path>
<path d="M215.4,32.6 L215.4,1.1 L231.2,1.1 L231.2,32.3 C231.2,40.4 235.3,44.2 241.5,44.2 C247.7,44.2 251.8,40.5 251.8,32.7 L251.8,1.1 L267.6,1.1 L267.6,32.2 C267.6,50.3 257.3,58.2 241.3,58.2 C225.4,58.3 215.4,50.2 215.4,32.6" id="Path"></path>
<path d="M291.4,1.1 L313.1,1.1 C333.1,1.1 344.8,12.6 344.8,28.8 L344.8,29 C344.8,45.2 333,57.2 312.8,57.2 L291.5,57.2 L291.4,1.1 L291.4,1.1 Z M313.3,43.4 C322.6,43.4 328.8,38.3 328.8,29.2 L328.8,29 C328.8,20 322.6,14.8 313.3,14.8 L307,14.8 L307,43.3 L313.3,43.4 L313.3,43.4 Z" id="Shape"></path>
<polygon id="Path" points="367.3 1.1 412.2 1.1 412.2 14.8 382.8 14.8 382.8 24.3 409.4 24.3 409.4 37.2 382.8 37.2 382.8 57.2 367.3 57.2"></polygon>
<polygon id="Path" points="433.8 1.1 449.3 1.1 449.3 43.6 476.5 43.6 476.5 57.2 433.8 57.2"></polygon>
<path d="M517.1,0.7 L532.1,0.7 L556,57.2 L539.3,57.2 L535.2,47.2 L513.6,47.2 L509.6,57.2 L493.3,57.2 L517.1,0.7 Z M530.8,35.1 L524.6,19.2 L518.3,35.1 L530.8,35.1 Z" id="Shape"></path>
<path d="M576,1.1 L602.5,1.1 C611.1,1.1 617,3.3 620.8,7.2 C624.1,10.4 625.8,14.7 625.8,20.3 L625.8,20.5 C625.8,29.1 621.2,34.8 614.3,37.7 L627.7,57.3 L609.7,57.3 L598.4,40.3 L591.6,40.3 L591.6,57.3 L576.1,57.3 L576,1.1 L576,1.1 Z M601.8,28.1 C607.1,28.1 610.1,25.5 610.1,21.5 L610.1,21.2 C610.1,16.8 606.9,14.6 601.7,14.6 L591.5,14.6 L591.5,28.1 L601.8,28.1 L601.8,28.1 Z" id="Shape"></path>
<polygon id="Path" points="648.2 1.1 693.3 1.1 693.3 14.4 663.6 14.4 663.6 22.8 690.5 22.8 690.5 35.1 663.6 35.1 663.6 44 693.7 44 693.7 57.2 648.2 57.2"></polygon>
<path d="M43.1,35.9 C40.9,40.8 36.3,44.3 30.3,44.3 C21.8,44.3 16,37.2 16,29.2 L16,29 C16,20.9 21.7,14 30.2,14 C36.6,14 41.5,17.9 43.5,23.3 L59.9,23.3 C57.3,9.9 45.5,0 30.3,0 C13,0 5.68434189e-14,13.1 5.68434189e-14,29.2 L5.68434189e-14,29.4 C5.68434189e-14,45.5 12.8,58.4 30.1,58.4 C44.9,58.4 56.5,48.8 59.5,36 L43.1,35.9 L43.1,35.9 Z" id="Path"></path>
</g>
<g id="Group">
<polygon id="Path" fill="#FFFFFF" points="312.8 91.6 269.9 67 262.5 63.8 87 65.1 87 154.1 312.8 154.2"></polygon>
<path d="M234.7,146 C236.8,138.8 236,132.2 232.5,127.3 C229.3,122.8 223.9,120.2 217.4,119.9 L94.3,118.3 C93.5,118.3 92.8,117.9 92.4,117.3 C92,116.7 91.9,115.9 92.1,115.1 C92.5,113.9 93.7,113 95,112.9 L219.2,111.3 C233.9,110.6 249.9,98.7 255.5,84.1 L262.6,65.6 C262.9,64.8 263,64 262.8,63.2 C254.8,27 222.5,1.42108547e-14 183.9,1.42108547e-14 C148.3,1.42108547e-14 118.1,23 107.3,54.9 C100.3,49.7 91.4,46.9 81.8,47.8 C64.7,49.5 51,63.2 49.3,80.3 C48.9,84.7 49.2,89 50.2,93 C22.3,93.8 1.42108547e-14,116.6 1.42108547e-14,144.7 C1.42108547e-14,147.2 0.2,149.7 0.5,152.2 C0.7,153.4 1.7,154.3 2.9,154.3 L230.1,154.3 C231.4,154.3 232.6,153.4 233,152.1 L234.7,146 Z" id="Path" fill="#F38020"></path>
<path d="M273.9,66.9 C272.8,66.9 271.6,66.9 270.5,67 C269.7,67 269,67.6 268.7,68.4 L263.9,85.1 C261.8,92.3 262.6,98.9 266.1,103.8 C269.3,108.3 274.7,110.9 281.2,111.2 L307.4,112.8 C308.2,112.8 308.9,113.2 309.3,113.8 C309.7,114.4 309.8,115.3 309.6,116 C309.2,117.2 308,118.1 306.7,118.2 L279.4,119.8 C264.6,120.5 248.7,132.4 243.1,147 L241.1,152.1 C240.7,153.1 241.4,154.1 242.5,154.1 L336.3,154.1 C337.4,154.1 338.4,153.4 338.7,152.3 C340.3,146.5 341.2,140.4 341.2,134.1 C341.2,97 311.1,66.9 273.9,66.9" id="Path" fill="#FAAE40"></path>
</g>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1062" height="155" version="1.1" viewBox="0 0 1062 155"><title>cf-logo-h</title><g id="Page-1" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="cf-logo-h" fill-rule="nonzero"><g id="Group" fill="#404041" transform="translate(367.600000, 95.800000)"><polygon id="Path" points="77.1 1.1 92.7 1.1 92.7 43.6 119.8 43.6 119.8 57.2 77.1 57.2"/><path id="Shape" d="M135.9,29.3 L135.9,29.2 C135.9,13.1 148.9,0 166.2,0 C183.5,0 196.3,12.9 196.3,29 L196.3,29.2 C196.3,45.3 183.3,58.4 166,58.4 C148.8,58.3 135.9,45.4 135.9,29.3 M180.5,29.3 L180.5,29.2 C180.5,21.1 174.7,14.1 166.1,14.1 C157.6,14.1 151.9,21 151.9,29.1 L151.9,29.3 C151.9,37.4 157.7,44.4 166.2,44.4 C174.8,44.3 180.5,37.4 180.5,29.3"/><path id="Path" d="M215.4,32.6 L215.4,1.1 L231.2,1.1 L231.2,32.3 C231.2,40.4 235.3,44.2 241.5,44.2 C247.7,44.2 251.8,40.5 251.8,32.7 L251.8,1.1 L267.6,1.1 L267.6,32.2 C267.6,50.3 257.3,58.2 241.3,58.2 C225.4,58.3 215.4,50.2 215.4,32.6"/><path id="Shape" d="M291.4,1.1 L313.1,1.1 C333.1,1.1 344.8,12.6 344.8,28.8 L344.8,29 C344.8,45.2 333,57.2 312.8,57.2 L291.5,57.2 L291.4,1.1 L291.4,1.1 Z M313.3,43.4 C322.6,43.4 328.8,38.3 328.8,29.2 L328.8,29 C328.8,20 322.6,14.8 313.3,14.8 L307,14.8 L307,43.3 L313.3,43.4 L313.3,43.4 Z"/><polygon id="Path" points="367.3 1.1 412.2 1.1 412.2 14.8 382.8 14.8 382.8 24.3 409.4 24.3 409.4 37.2 382.8 37.2 382.8 57.2 367.3 57.2"/><polygon id="Path" points="433.8 1.1 449.3 1.1 449.3 43.6 476.5 43.6 476.5 57.2 433.8 57.2"/><path id="Shape" d="M517.1,0.7 L532.1,0.7 L556,57.2 L539.3,57.2 L535.2,47.2 L513.6,47.2 L509.6,57.2 L493.3,57.2 L517.1,0.7 Z M530.8,35.1 L524.6,19.2 L518.3,35.1 L530.8,35.1 Z"/><path id="Shape" d="M576,1.1 L602.5,1.1 C611.1,1.1 617,3.3 620.8,7.2 C624.1,10.4 625.8,14.7 625.8,20.3 L625.8,20.5 C625.8,29.1 621.2,34.8 614.3,37.7 L627.7,57.3 L609.7,57.3 L598.4,40.3 L591.6,40.3 L591.6,57.3 L576.1,57.3 L576,1.1 L576,1.1 Z M601.8,28.1 C607.1,28.1 610.1,25.5 610.1,21.5 L610.1,21.2 C610.1,16.8 606.9,14.6 601.7,14.6 L591.5,14.6 L591.5,28.1 L601.8,28.1 L601.8,28.1 Z"/><polygon id="Path" points="648.2 1.1 693.3 1.1 693.3 14.4 663.6 14.4 663.6 22.8 690.5 22.8 690.5 35.1 663.6 35.1 663.6 44 693.7 44 693.7 57.2 648.2 57.2"/><path id="Path" d="M43.1,35.9 C40.9,40.8 36.3,44.3 30.3,44.3 C21.8,44.3 16,37.2 16,29.2 L16,29 C16,20.9 21.7,14 30.2,14 C36.6,14 41.5,17.9 43.5,23.3 L59.9,23.3 C57.3,9.9 45.5,0 30.3,0 C13,0 5.68434189e-14,13.1 5.68434189e-14,29.2 L5.68434189e-14,29.4 C5.68434189e-14,45.5 12.8,58.4 30.1,58.4 C44.9,58.4 56.5,48.8 59.5,36 L43.1,35.9 L43.1,35.9 Z"/></g><g id="Group"><polygon id="Path" fill="#FFF" points="312.8 91.6 269.9 67 262.5 63.8 87 65.1 87 154.1 312.8 154.2"/><path id="Path" fill="#F38020" d="M234.7,146 C236.8,138.8 236,132.2 232.5,127.3 C229.3,122.8 223.9,120.2 217.4,119.9 L94.3,118.3 C93.5,118.3 92.8,117.9 92.4,117.3 C92,116.7 91.9,115.9 92.1,115.1 C92.5,113.9 93.7,113 95,112.9 L219.2,111.3 C233.9,110.6 249.9,98.7 255.5,84.1 L262.6,65.6 C262.9,64.8 263,64 262.8,63.2 C254.8,27 222.5,1.42108547e-14 183.9,1.42108547e-14 C148.3,1.42108547e-14 118.1,23 107.3,54.9 C100.3,49.7 91.4,46.9 81.8,47.8 C64.7,49.5 51,63.2 49.3,80.3 C48.9,84.7 49.2,89 50.2,93 C22.3,93.8 1.42108547e-14,116.6 1.42108547e-14,144.7 C1.42108547e-14,147.2 0.2,149.7 0.5,152.2 C0.7,153.4 1.7,154.3 2.9,154.3 L230.1,154.3 C231.4,154.3 232.6,153.4 233,152.1 L234.7,146 Z"/><path id="Path" fill="#FAAE40" d="M273.9,66.9 C272.8,66.9 271.6,66.9 270.5,67 C269.7,67 269,67.6 268.7,68.4 L263.9,85.1 C261.8,92.3 262.6,98.9 266.1,103.8 C269.3,108.3 274.7,110.9 281.2,111.2 L307.4,112.8 C308.2,112.8 308.9,113.2 309.3,113.8 C309.7,114.4 309.8,115.3 309.6,116 C309.2,117.2 308,118.1 306.7,118.2 L279.4,119.8 C264.6,120.5 248.7,132.4 243.1,147 L241.1,152.1 C240.7,153.1 241.4,154.1 242.5,154.1 L336.3,154.1 C337.4,154.1 338.4,153.4 338.7,152.3 C340.3,146.5 341.2,140.4 341.2,134.1 C341.2,97 311.1,66.9 273.9,66.9"/></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 91 KiB

Some files were not shown because too many files have changed in this diff Show More