Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
李少辉-开发者
gitlab-foss
提交
e610332e
G
gitlab-foss
项目概览
李少辉-开发者
/
gitlab-foss
通知
15
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
gitlab-foss
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
e610332e
编写于
9月 21, 2017
作者:
M
Michael Kozono
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Normalize existing persisted DNs
上级
14ed20d6
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
285 addition
and
0 deletion
+285
-0
db/post_migrate/20170921101004_normalize_ldap_extern_uids.rb
db/post_migrate/20170921101004_normalize_ldap_extern_uids.rb
+285
-0
未找到文件。
db/post_migrate/20170921101004_normalize_ldap_extern_uids.rb
0 → 100644
浏览文件 @
e610332e
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class
NormalizeLdapExternUids
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
class
Identity
<
ActiveRecord
::
Base
self
.
table_name
=
'identities'
end
# Copied this class to make this migration resilient to future code changes.
# And if the normalize behavior is changed in the future, it must be
# accompanied by another migration.
module
Gitlab
module
LDAP
MalformedDnError
=
Class
.
new
(
StandardError
)
UnsupportedDnFormatError
=
Class
.
new
(
StandardError
)
class
DN
##
# Initialize a DN, escaping as required. Pass in attributes in name/value
# pairs. If there is a left over argument, it will be appended to the dn
# without escaping (useful for a base string).
#
# Most uses of this class will be to escape a DN, rather than to parse it,
# so storing the dn as an escaped String and parsing parts as required
# with a state machine seems sensible.
def
initialize
(
*
args
)
buffer
=
StringIO
.
new
args
.
each_index
do
|
index
|
buffer
<<
"="
if
index
.
odd?
buffer
<<
","
if
index
.
even?
&&
index
!=
0
arg
=
args
[
index
].
downcase
buffer
<<
if
index
<
args
.
length
-
1
||
index
.
odd?
self
.
class
.
escape
(
arg
)
else
arg
end
end
@dn
=
buffer
.
string
end
##
# Parse a DN into key value pairs using ASN from
# http://tools.ietf.org/html/rfc2253 section 3.
# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/PerceivedComplexity
def
each_pair
state
=
:key
key
=
StringIO
.
new
value
=
StringIO
.
new
hex_buffer
=
""
@dn
.
each_char
do
|
char
|
case
state
when
:key
then
case
char
when
'a'
..
'z'
then
state
=
:key_normal
key
<<
char
when
'0'
..
'9'
then
state
=
:key_oid
key
<<
char
when
' '
then
state
=
:key
else
raise
(
MalformedDnError
,
"Unrecognized first character of an RDN attribute type name
\"
#{
char
}
\"
"
)
end
when
:key_normal
then
case
char
when
'='
then
state
=
:value
when
'a'
..
'z'
,
'0'
..
'9'
,
'-'
,
' '
then
key
<<
char
else
raise
(
MalformedDnError
,
"Unrecognized RDN attribute type name character
\"
#{
char
}
\"
"
)
end
when
:key_oid
then
case
char
when
'='
then
state
=
:value
when
'0'
..
'9'
,
'.'
,
' '
then
key
<<
char
else
raise
(
MalformedDnError
,
"Unrecognized RDN OID attribute type name character
\"
#{
char
}
\"
"
)
end
when
:value
then
case
char
when
'\\'
then
state
=
:value_normal_escape
when
'"'
then
state
=
:value_quoted
when
' '
then
state
=
:value
when
'#'
then
state
=
:value_hexstring
value
<<
char
when
','
then
state
=
:key
yield
key
.
string
.
strip
,
value
.
string
.
rstrip
key
=
StringIO
.
new
value
=
StringIO
.
new
else
state
=
:value_normal
value
<<
char
end
when
:value_normal
then
case
char
when
'\\'
then
state
=
:value_normal_escape
when
','
then
state
=
:key
yield
key
.
string
.
strip
,
value
.
string
.
rstrip
key
=
StringIO
.
new
value
=
StringIO
.
new
when
'+'
then
raise
(
UnsupportedDnFormatError
,
"Multivalued RDNs are not supported"
)
else
value
<<
char
end
when
:value_normal_escape
then
case
char
when
'0'
..
'9'
,
'a'
..
'f'
then
state
=
:value_normal_escape_hex
hex_buffer
=
char
when
/\s/
then
state
=
:value_normal_escape_whitespace
value
<<
char
else
state
=
:value_normal
value
<<
char
end
when
:value_normal_escape_hex
then
case
char
when
'0'
..
'9'
,
'a'
..
'f'
then
state
=
:value_normal
value
<<
"
#{
hex_buffer
}#{
char
}
"
.
to_i
(
16
).
chr
else
raise
(
MalformedDnError
,
"Invalid escaped hex code
\"\\
#{
hex_buffer
}#{
char
}
\"
"
)
end
when
:value_normal_escape_whitespace
then
case
char
when
'\\'
then
state
=
:value_normal_escape
when
','
then
state
=
:key
yield
key
.
string
.
strip
,
value
.
string
# Don't strip trailing escaped space!
key
=
StringIO
.
new
value
=
StringIO
.
new
when
'+'
then
raise
(
UnsupportedDnFormatError
,
"Multivalued RDNs are not supported"
)
else
value
<<
char
end
when
:value_quoted
then
case
char
when
'\\'
then
state
=
:value_quoted_escape
when
'"'
then
state
=
:value_end
else
value
<<
char
end
when
:value_quoted_escape
then
case
char
when
'0'
..
'9'
,
'a'
..
'f'
then
state
=
:value_quoted_escape_hex
hex_buffer
=
char
else
state
=
:value_quoted
value
<<
char
end
when
:value_quoted_escape_hex
then
case
char
when
'0'
..
'9'
,
'a'
..
'f'
then
state
=
:value_quoted
value
<<
"
#{
hex_buffer
}#{
char
}
"
.
to_i
(
16
).
chr
else
raise
(
MalformedDnError
,
"Expected the second character of a hex pair inside a double quoted value, but got
\"
#{
char
}
\"
"
)
end
when
:value_hexstring
then
case
char
when
'0'
..
'9'
,
'a'
..
'f'
then
state
=
:value_hexstring_hex
value
<<
char
when
' '
then
state
=
:value_end
when
','
then
state
=
:key
yield
key
.
string
.
strip
,
value
.
string
.
rstrip
key
=
StringIO
.
new
value
=
StringIO
.
new
else
raise
(
MalformedDnError
,
"Expected the first character of a hex pair, but got
\"
#{
char
}
\"
"
)
end
when
:value_hexstring_hex
then
case
char
when
'0'
..
'9'
,
'a'
..
'f'
then
state
=
:value_hexstring
value
<<
char
else
raise
(
MalformedDnError
,
"Expected the second character of a hex pair, but got
\"
#{
char
}
\"
"
)
end
when
:value_end
then
case
char
when
' '
then
state
=
:value_end
when
','
then
state
=
:key
yield
key
.
string
.
strip
,
value
.
string
.
rstrip
key
=
StringIO
.
new
value
=
StringIO
.
new
else
raise
(
MalformedDnError
,
"Expected the end of an attribute value, but got
\"
#{
char
}
\"
"
)
end
else
raise
"Fell out of state machine"
end
end
# Last pair
raise
(
MalformedDnError
,
'DN string ended unexpectedly'
)
unless
[
:value
,
:value_normal
,
:value_hexstring
,
:value_end
].
include?
state
yield
key
.
string
.
strip
,
value
.
string
.
rstrip
end
##
# Returns the DN as an array in the form expected by the constructor.
def
to_a
a
=
[]
self
.
each_pair
{
|
key
,
value
|
a
<<
key
<<
value
}
unless
@dn
.
empty?
a
end
##
# Return the DN as an escaped string.
def
to_s
@dn
end
##
# Return the DN as an escaped and normalized string.
def
to_s_normalized
self
.
class
.
new
(
*
to_a
).
to_s
end
# https://tools.ietf.org/html/rfc4514 section 2.4 lists these exceptions
# for DN values. All of the following must be escaped in any normal string
# using a single backslash ('\') as escape. The space character is left
# out here because in a "normalized" string, spaces should only be escaped
# if necessary (i.e. leading or trailing space).
NORMAL_ESCAPES
=
[
','
,
'+'
,
'"'
,
'\\'
,
'<'
,
'>'
,
';'
,
'='
].
freeze
# The following must be represented as escaped hex
HEX_ESCAPES
=
{
"
\n
"
=>
'\0a'
,
"
\r
"
=>
'\0d'
}.
freeze
# Compiled character class regexp using the keys from the above hash, and
# checking for a space or # at the start, or space at the end, of the
# string.
ESCAPE_RE
=
Regexp
.
new
(
"(^ |^#| $|["
+
NORMAL_ESCAPES
.
map
{
|
e
|
Regexp
.
escape
(
e
)
}.
join
+
"])"
)
HEX_ESCAPE_RE
=
Regexp
.
new
(
"(["
+
HEX_ESCAPES
.
keys
.
map
{
|
e
|
Regexp
.
escape
(
e
)
}.
join
+
"])"
)
##
# Escape a string for use in a DN value
def
self
.
escape
(
string
)
escaped
=
string
.
gsub
(
ESCAPE_RE
)
{
|
char
|
"
\\
"
+
char
}
escaped
.
gsub
(
HEX_ESCAPE_RE
)
{
|
char
|
HEX_ESCAPES
[
char
]
}
end
##
# Proxy all other requests to the string object, because a DN is mainly
# used within the library as a string
# rubocop:disable GitlabSecurity/PublicSend
def
method_missing
(
method
,
*
args
,
&
block
)
@dn
.
send
(
method
,
*
args
,
&
block
)
end
end
end
end
def
up
ldap_identities
=
Identity
.
where
(
"provider like 'ldap%'"
)
ldap_identities
.
find_each
do
|
identity
|
begin
identity
.
extern_uid
=
Gitlab
::
LDAP
::
DN
.
new
(
identity
.
extern_uid
).
to_s_normalized
unless
identity
.
save
say
"Unable to normalize
\"
#{
identity
.
extern_uid
}
\"
. Skipping."
end
rescue
Gitlab
::
LDAP
::
MalformedDnError
,
Gitlab
::
LDAP
::
UnsupportedDnFormatError
=>
e
say
"Unable to normalize
\"
#{
identity
.
extern_uid
}
\"
due to
\"
#{
e
.
message
}
\"
. Skipping."
end
end
end
def
down
end
end
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录