working commit
This commit is contained in:
Executable
+29
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
MAX_SIZE=1024 # 1 MB limit in KB
|
||||||
|
for file in $(git diff --cached --name-only --diff-filter=ACM); do
|
||||||
|
if [ ! -e "$file" ]; then continue; fi
|
||||||
|
size=$(du -k "$file" | cut -f1)
|
||||||
|
if [ $size -gt $MAX_SIZE ]; then
|
||||||
|
echo "Error: File $file is larger than the allowed size of $((MAX_SIZE / 1024)) MB."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
status=0
|
||||||
|
|
||||||
|
for file in $(git diff --cached --name-only | grep -E '\.go$'); do
|
||||||
|
badfile=$(gofmt -l "$file")
|
||||||
|
if test -n "$badfile" ; then
|
||||||
|
echo "Error: file needs gofmt: $badfile"
|
||||||
|
status=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# If any files were not formatted, exit with a non-zero status to abort the commit.
|
||||||
|
if [ "$status" -ne 0 ]; then
|
||||||
|
echo "git pre-commit check failed: some Go files are not formatted."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
exit 0
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
*~
|
||||||
|
autom4te.cache
|
||||||
|
Makefile
|
||||||
|
config.status
|
||||||
|
config.log
|
||||||
|
cmd/mbased/mbased
|
||||||
|
cmd/mbasectl/mbasectl
|
||||||
|
*.db
|
||||||
|
*.db-shm
|
||||||
|
*.db-wal
|
||||||
|
*.tar.*
|
||||||
|
*.tmp.*
|
||||||
|
*.tar
|
||||||
|
*.bin
|
||||||
|
tmp
|
||||||
|
mbased
|
||||||
|
mbasectl
|
||||||
|
DIST
|
||||||
|
*.tar.gz
|
||||||
|
*.deb
|
||||||
|
*.rpm
|
||||||
|
mbased.service
|
||||||
|
variant.go
|
||||||
|
initrc/mbased
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
FROM alpine:3.20 as builder
|
||||||
|
|
||||||
|
RUN apk --no-cache add make binutils gcc libc-dev automake autoconf curl
|
||||||
|
RUN curl -o /usr/local/lib/go.tar.gz https://dl.google.com/go/go1.24.4.linux-amd64.tar.gz
|
||||||
|
RUN cd /usr/local/lib && tar xzf go.tar.gz
|
||||||
|
RUN cd /usr/local/bin && ln -sf ../lib/go/bin/* .
|
||||||
|
|
||||||
|
WORKDIR /app/src/
|
||||||
|
COPY go.mod go.sum .
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN ./configure --prefix=/app
|
||||||
|
RUN make clean all install
|
||||||
|
RUN rm -rf /app/src
|
||||||
|
|
||||||
|
FROM alpine:3.20
|
||||||
|
COPY --from=builder /app /app
|
||||||
|
RUN chmod 1777 /var
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
#USER daemon:daemon
|
||||||
|
ENTRYPOINT ["/app/sbin/certmanagerd"]
|
||||||
+119
@@ -0,0 +1,119 @@
|
|||||||
|
|
||||||
|
AUTOMAKE_OPTIONS = foreign no-dependencies no-installinfo
|
||||||
|
|
||||||
|
SUFFIXES = .go
|
||||||
|
OBJEXT= none
|
||||||
|
|
||||||
|
|
||||||
|
sbin_PROGRAMS = mbased mbasedump mbaserestore mbaseadmin
|
||||||
|
bin_PROGRAMS = mbasectl
|
||||||
|
|
||||||
|
mbased_SOURCES = cmd/mbased/main.go
|
||||||
|
mbased$(EXEEXT): $(mbased_SOURCES) $(EXTRA_mbased_SOURCES)
|
||||||
|
env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o mbased$(EXEEXT) $(mbased_SOURCES)
|
||||||
|
|
||||||
|
mbasedump_SOURCES = cmd/mbasedump/maindump.go
|
||||||
|
mbasedump$(EXEEXT): $(mbasedump_SOURCES) $(EXTRA_mbased_SOURCES)
|
||||||
|
env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o mbasedump$(EXEEXT) $(mbasedump_SOURCES)
|
||||||
|
|
||||||
|
mbaserestore_SOURCES = cmd/mbaserestore/mainrestore.go
|
||||||
|
mbaserestore$(EXEEXT): $(mbaserestore_SOURCES) $(EXTRA_mbased_SOURCES)
|
||||||
|
env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o mbaserestore$(EXEEXT) $(mbaserestore_SOURCES)
|
||||||
|
|
||||||
|
mbasectl_SOURCES = cmd/mbasectl/main.go \
|
||||||
|
cmd/mbasectl/account.go \
|
||||||
|
cmd/mbasectl/grant.go \
|
||||||
|
cmd/mbasectl/dump.go
|
||||||
|
|
||||||
|
|
||||||
|
mbasectl$(EXEEXT): $(mbasectl_SOURCES) $(EXTRA_mbased_SOURCES)
|
||||||
|
env CGO_ENABLED=0 $(GO) build $(GOFLAGS) -o mbasectl$(EXEEXT) $(mbasectl_SOURCES)
|
||||||
|
|
||||||
|
mbaseadmin_SOURCES = cmd/mbaseadmin/main.go \
|
||||||
|
cmd/mbaseadmin/account.go \
|
||||||
|
cmd/mbaseadmin/grant.go
|
||||||
|
|
||||||
|
mbaseadmin$(EXEEXT): $(mbaseadmin_SOURCES) $(EXTRA_mbased_SOURCES)
|
||||||
|
env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o mbaseadmin$(EXEEXT) $(mbaseadmin_SOURCES)
|
||||||
|
|
||||||
|
EXTRA_mbased_SOURCES =
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
Changelog.txt \
|
||||||
|
Containerfile \
|
||||||
|
etc/mbase/mbased.yaml \
|
||||||
|
.gitignore \
|
||||||
|
go.mod \
|
||||||
|
go.sum \
|
||||||
|
proto/cmctl.proto \
|
||||||
|
README.md \
|
||||||
|
test/account_test.go \
|
||||||
|
test/dump_test.go \
|
||||||
|
test/hello_test.go \
|
||||||
|
test/Makefile.am \
|
||||||
|
test/Makefile.in \
|
||||||
|
test/server.go \
|
||||||
|
test/support.go \
|
||||||
|
vendor/*
|
||||||
|
|
||||||
|
GENDIR=pkg/mbctl
|
||||||
|
PROTOSRC = proto/mbctl.proto
|
||||||
|
|
||||||
|
rpc:
|
||||||
|
mkdir -p $(GENDIR)
|
||||||
|
$(PROTOC) --proto_path=proto --go_out=$(GENDIR) --go-grpc_out=$(GENDIR) $(PROTOSRC)
|
||||||
|
|
||||||
|
SYSTEMD_LIBDIR = /lib/systemd/system
|
||||||
|
|
||||||
|
FREEBSD_LOCALBASE = /usr/local
|
||||||
|
FREEBSD_RCDIR = $(FREEBSD_LOCALBASE)/etc/rc.d
|
||||||
|
LINUX_SYSTEMDDIR = /lib/systemd/system
|
||||||
|
|
||||||
|
|
||||||
|
install-data-local:
|
||||||
|
test -z $(DESTDIR)$(SRV_CONFDIR) || $(MKDIR_P) $(DESTDIR)$(SRV_CONFDIR)
|
||||||
|
test -z $(DESTDIR)$(SRV_LOGDIR) || $(MKDIR_P) $(DESTDIR)$(SRV_LOGDIR)
|
||||||
|
test -z $(DESTDIR)$(SRV_RUNDIR) || $(MKDIR_P) $(DESTDIR)$(SRV_RUNDIR)
|
||||||
|
test -z $(DESTDIR)$(SRV_DATADIR) || $(MKDIR_P) $(DESTDIR)$(SRV_DATADIR)
|
||||||
|
test -z $(DESTDIR)$(SYSTEMD_LIBDIR) || $(MKDIR_P) $(DESTDIR)$(SYSTEMD_LIBDIR)
|
||||||
|
if FREEBSD_OS
|
||||||
|
test -z $(DESTDIR)$(FREEBSD_RCDIR) || $(MKDIR_P) $(DESTDIR)$(FREEBSD_RCDIR)
|
||||||
|
$(INSTALL_DATA) initrc/mbased $(DESTDIR)$(FREEBSD_RCDIR)
|
||||||
|
chmod a+x $(DESTDIR)$(FREEBSD_RCDIR)/mbased
|
||||||
|
endif
|
||||||
|
if LINUX_OS
|
||||||
|
if SYSTEMD
|
||||||
|
test -z $(DESTDIR)$(LINUX_SYSTEMDDIR) || $(MKDIR_P) $(DESTDIR)$(LINUX_SYSTEMDDIR)
|
||||||
|
$(INSTALL_DATA) initrc/mbased.service $(DESTDIR)$(LINUX_SYSTEMDDIR)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
format:
|
||||||
|
for dir in $$(find app pkg cmd -type d); do \
|
||||||
|
(cd $$dir && $(GO) fmt .); \
|
||||||
|
done
|
||||||
|
|
||||||
|
run:
|
||||||
|
test -z $(DESTDIR)$(SRV_LOGDIR) || $(MKDIR_P) $(DESTDIR)$(SRV_LOGDIR)
|
||||||
|
test -z $(DESTDIR)$(SRV_RUNDIR) || $(MKDIR_P) $(DESTDIR)$(SRV_RUNDIR)
|
||||||
|
test -z $(DESTDIR)$(SRV_DATADIR) || $(MKDIR_P) $(DESTDIR)$(SRV_DATADIR)
|
||||||
|
env CGO_ENABLED=1 $(GO) run $(GOFLAGS) ./cmd/mbased/... --daemon=false
|
||||||
|
|
||||||
|
|
||||||
|
distclean-local: clean
|
||||||
|
rm -rf autom4te.cache
|
||||||
|
|
||||||
|
clean-local:
|
||||||
|
rm -f */*/*~
|
||||||
|
rm -f */*~
|
||||||
|
rm -f *~
|
||||||
|
rm -f cmd/mbaseadmin/mbaseadmin
|
||||||
|
rm -f cmd/mbasectl/mbasectl
|
||||||
|
rm -f cmd/mbased/mbased
|
||||||
|
rm -f cmd/mbasedump/mbasedump
|
||||||
|
rm -f cmd/mbaselocal/mbaselocal
|
||||||
|
rm -f cmd/mbaserestore/mbaserestore
|
||||||
|
rm -rf autom4te.cache
|
||||||
|
rm -rf tmp/
|
||||||
|
|
||||||
+925
@@ -0,0 +1,925 @@
|
|||||||
|
# Makefile.in generated by automake 1.17 from Makefile.am.
|
||||||
|
# @configure_input@
|
||||||
|
|
||||||
|
# Copyright (C) 1994-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
|
# with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||||
|
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
@SET_MAKE@
|
||||||
|
|
||||||
|
VPATH = @srcdir@
|
||||||
|
am__is_gnu_make = { \
|
||||||
|
if test -z '$(MAKELEVEL)'; then \
|
||||||
|
false; \
|
||||||
|
elif test -n '$(MAKE_HOST)'; then \
|
||||||
|
true; \
|
||||||
|
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||||
|
true; \
|
||||||
|
else \
|
||||||
|
false; \
|
||||||
|
fi; \
|
||||||
|
}
|
||||||
|
am__make_running_with_option = \
|
||||||
|
case $${target_option-} in \
|
||||||
|
?) ;; \
|
||||||
|
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||||
|
"target option '$${target_option-}' specified" >&2; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
has_opt=no; \
|
||||||
|
sane_makeflags=$$MAKEFLAGS; \
|
||||||
|
if $(am__is_gnu_make); then \
|
||||||
|
sane_makeflags=$$MFLAGS; \
|
||||||
|
else \
|
||||||
|
case $$MAKEFLAGS in \
|
||||||
|
*\\[\ \ ]*) \
|
||||||
|
bs=\\; \
|
||||||
|
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||||
|
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||||
|
esac; \
|
||||||
|
fi; \
|
||||||
|
skip_next=no; \
|
||||||
|
strip_trailopt () \
|
||||||
|
{ \
|
||||||
|
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||||
|
}; \
|
||||||
|
for flg in $$sane_makeflags; do \
|
||||||
|
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||||
|
case $$flg in \
|
||||||
|
*=*|--*) continue;; \
|
||||||
|
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||||
|
-*I?*) strip_trailopt 'I';; \
|
||||||
|
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||||
|
-*O?*) strip_trailopt 'O';; \
|
||||||
|
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||||
|
-*l?*) strip_trailopt 'l';; \
|
||||||
|
-[dEDm]) skip_next=yes;; \
|
||||||
|
-[JT]) skip_next=yes;; \
|
||||||
|
esac; \
|
||||||
|
case $$flg in \
|
||||||
|
*$$target_option*) has_opt=yes; break;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
test $$has_opt = yes
|
||||||
|
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||||
|
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||||
|
am__rm_f = rm -f $(am__rm_f_notfound)
|
||||||
|
am__rm_rf = rm -rf $(am__rm_f_notfound)
|
||||||
|
pkgdatadir = $(datadir)/@PACKAGE@
|
||||||
|
pkgincludedir = $(includedir)/@PACKAGE@
|
||||||
|
pkglibdir = $(libdir)/@PACKAGE@
|
||||||
|
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||||
|
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||||
|
install_sh_DATA = $(install_sh) -c -m 644
|
||||||
|
install_sh_PROGRAM = $(install_sh) -c
|
||||||
|
install_sh_SCRIPT = $(install_sh) -c
|
||||||
|
INSTALL_HEADER = $(INSTALL_DATA)
|
||||||
|
transform = $(program_transform_name)
|
||||||
|
NORMAL_INSTALL = :
|
||||||
|
PRE_INSTALL = :
|
||||||
|
POST_INSTALL = :
|
||||||
|
NORMAL_UNINSTALL = :
|
||||||
|
PRE_UNINSTALL = :
|
||||||
|
POST_UNINSTALL = :
|
||||||
|
build_triplet = @build@
|
||||||
|
host_triplet = @host@
|
||||||
|
sbin_PROGRAMS = mbased$(EXEEXT) mbasedump$(EXEEXT) \
|
||||||
|
mbaserestore$(EXEEXT) mbaseadmin$(EXEEXT)
|
||||||
|
bin_PROGRAMS = mbasectl$(EXEEXT)
|
||||||
|
subdir = .
|
||||||
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
|
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||||
|
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||||
|
$(ACLOCAL_M4)
|
||||||
|
DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
|
||||||
|
$(am__configure_deps) $(am__DIST_COMMON)
|
||||||
|
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
|
||||||
|
configure.lineno config.status.lineno
|
||||||
|
mkinstalldirs = $(install_sh) -d
|
||||||
|
CONFIG_CLEAN_FILES = app/config/variant.go initrc/mbased.service \
|
||||||
|
initrc/mbased
|
||||||
|
CONFIG_CLEAN_VPATH_FILES =
|
||||||
|
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)"
|
||||||
|
PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS)
|
||||||
|
am_mbaseadmin_OBJECTS =
|
||||||
|
mbaseadmin_OBJECTS = $(am_mbaseadmin_OBJECTS)
|
||||||
|
mbaseadmin_LDADD = $(LDADD)
|
||||||
|
am_mbasectl_OBJECTS =
|
||||||
|
mbasectl_OBJECTS = $(am_mbasectl_OBJECTS)
|
||||||
|
mbasectl_LDADD = $(LDADD)
|
||||||
|
am_mbased_OBJECTS =
|
||||||
|
mbased_OBJECTS = $(am_mbased_OBJECTS)
|
||||||
|
mbased_LDADD = $(LDADD)
|
||||||
|
am_mbasedump_OBJECTS =
|
||||||
|
mbasedump_OBJECTS = $(am_mbasedump_OBJECTS)
|
||||||
|
mbasedump_LDADD = $(LDADD)
|
||||||
|
am_mbaserestore_OBJECTS =
|
||||||
|
mbaserestore_OBJECTS = $(am_mbaserestore_OBJECTS)
|
||||||
|
mbaserestore_LDADD = $(LDADD)
|
||||||
|
AM_V_P = $(am__v_P_@AM_V@)
|
||||||
|
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||||
|
am__v_P_0 = false
|
||||||
|
am__v_P_1 = :
|
||||||
|
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||||
|
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||||
|
am__v_GEN_0 = @echo " GEN " $@;
|
||||||
|
am__v_GEN_1 =
|
||||||
|
AM_V_at = $(am__v_at_@AM_V@)
|
||||||
|
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||||
|
am__v_at_0 = @
|
||||||
|
am__v_at_1 =
|
||||||
|
DEFAULT_INCLUDES = -I.@am__isrc@
|
||||||
|
depcomp =
|
||||||
|
am__maybe_remake_depfiles =
|
||||||
|
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||||
|
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||||
|
AM_V_CC = $(am__v_CC_@AM_V@)
|
||||||
|
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
|
||||||
|
am__v_CC_0 = @echo " CC " $@;
|
||||||
|
am__v_CC_1 =
|
||||||
|
CCLD = $(CC)
|
||||||
|
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||||
|
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
|
||||||
|
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
|
||||||
|
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||||
|
am__v_CCLD_1 =
|
||||||
|
SOURCES = $(mbaseadmin_SOURCES) $(mbasectl_SOURCES) $(mbased_SOURCES) \
|
||||||
|
$(EXTRA_mbased_SOURCES) $(mbasedump_SOURCES) \
|
||||||
|
$(mbaserestore_SOURCES)
|
||||||
|
DIST_SOURCES = $(mbaseadmin_SOURCES) $(mbasectl_SOURCES) \
|
||||||
|
$(mbased_SOURCES) $(EXTRA_mbased_SOURCES) $(mbasedump_SOURCES) \
|
||||||
|
$(mbaserestore_SOURCES)
|
||||||
|
am__can_run_installinfo = \
|
||||||
|
case $$AM_UPDATE_INFO_DIR in \
|
||||||
|
n|no|NO) false;; \
|
||||||
|
*) (install-info --version) >/dev/null 2>&1;; \
|
||||||
|
esac
|
||||||
|
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||||
|
# Read a list of newline-separated strings from the standard input,
|
||||||
|
# and print each of them once, without duplicates. Input order is
|
||||||
|
# *not* preserved.
|
||||||
|
am__uniquify_input = $(AWK) '\
|
||||||
|
BEGIN { nonempty = 0; } \
|
||||||
|
{ items[$$0] = 1; nonempty = 1; } \
|
||||||
|
END { if (nonempty) { for (i in items) print i; }; } \
|
||||||
|
'
|
||||||
|
# Make sure the list of sources is unique. This is necessary because,
|
||||||
|
# e.g., the same source file might be shared among _SOURCES variables
|
||||||
|
# for different programs/libraries.
|
||||||
|
am__define_uniq_tagged_files = \
|
||||||
|
list='$(am__tagged_files)'; \
|
||||||
|
unique=`for i in $$list; do \
|
||||||
|
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||||
|
done | $(am__uniquify_input)`
|
||||||
|
AM_RECURSIVE_TARGETS = cscope
|
||||||
|
am__DIST_COMMON = $(srcdir)/Makefile.in \
|
||||||
|
$(top_srcdir)/app/config/variant.go.in \
|
||||||
|
$(top_srcdir)/initrc/mbased.in \
|
||||||
|
$(top_srcdir)/initrc/mbased.service.in README.md compile \
|
||||||
|
config.guess config.sub install-sh missing
|
||||||
|
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
distdir = $(PACKAGE)-$(VERSION)
|
||||||
|
top_distdir = $(distdir)
|
||||||
|
am__remove_distdir = \
|
||||||
|
if test -d "$(distdir)"; then \
|
||||||
|
find "$(distdir)" -type d ! -perm -700 -exec chmod u+rwx {} ';' \
|
||||||
|
; rm -rf "$(distdir)" \
|
||||||
|
|| { sleep 5 && rm -rf "$(distdir)"; }; \
|
||||||
|
else :; fi
|
||||||
|
am__post_remove_distdir = $(am__remove_distdir)
|
||||||
|
DIST_ARCHIVES = $(distdir).tar.gz
|
||||||
|
GZIP_ENV = -9
|
||||||
|
DIST_TARGETS = dist-gzip
|
||||||
|
# Exists only to be overridden by the user if desired.
|
||||||
|
AM_DISTCHECK_DVI_TARGET = dvi
|
||||||
|
distuninstallcheck_listfiles = find . -type f -print
|
||||||
|
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
|
||||||
|
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
|
||||||
|
distcleancheck_listfiles = \
|
||||||
|
find . \( -type f -a \! \
|
||||||
|
\( -name .nfs* -o -name .smb* -o -name .__afs* \) \) -print
|
||||||
|
ACLOCAL = @ACLOCAL@
|
||||||
|
AMTAR = @AMTAR@
|
||||||
|
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||||
|
AUTOCONF = @AUTOCONF@
|
||||||
|
AUTOHEADER = @AUTOHEADER@
|
||||||
|
AUTOMAKE = @AUTOMAKE@
|
||||||
|
AWK = @AWK@
|
||||||
|
CC = @CC@
|
||||||
|
CCDEPMODE = @CCDEPMODE@
|
||||||
|
CFLAGS = @CFLAGS@
|
||||||
|
CP = @CP@
|
||||||
|
CPIO = @CPIO@
|
||||||
|
CPPFLAGS = @CPPFLAGS@
|
||||||
|
CSCOPE = @CSCOPE@
|
||||||
|
CTAGS = @CTAGS@
|
||||||
|
CYGPATH_W = @CYGPATH_W@
|
||||||
|
DBUILDPACKAGE = @DBUILDPACKAGE@
|
||||||
|
DEFS = @DEFS@
|
||||||
|
DEPDIR = @DEPDIR@
|
||||||
|
ECHO_C = @ECHO_C@
|
||||||
|
ECHO_N = @ECHO_N@
|
||||||
|
ECHO_T = @ECHO_T@
|
||||||
|
ETAGS = @ETAGS@
|
||||||
|
EXEEXT = @EXEEXT@
|
||||||
|
GO = @GO@
|
||||||
|
HAVE_GO = @HAVE_GO@
|
||||||
|
INSTALL = @INSTALL@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||||
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
|
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||||
|
LDFLAGS = @LDFLAGS@
|
||||||
|
LIBOBJS = @LIBOBJS@
|
||||||
|
LIBS = @LIBS@
|
||||||
|
LTLIBOBJS = @LTLIBOBJS@
|
||||||
|
MAKEINFO = @MAKEINFO@
|
||||||
|
MKDIR_P = @MKDIR_P@
|
||||||
|
OBJEXT = none
|
||||||
|
PACKAGE = @PACKAGE@
|
||||||
|
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||||
|
PACKAGE_NAME = @PACKAGE_NAME@
|
||||||
|
PACKAGE_STRING = @PACKAGE_STRING@
|
||||||
|
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||||
|
PACKAGE_URL = @PACKAGE_URL@
|
||||||
|
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||||
|
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||||
|
PODMAN = @PODMAN@
|
||||||
|
PROTOC = @PROTOC@
|
||||||
|
ROOT_GROUP = @ROOT_GROUP@
|
||||||
|
RPMBUILD = @RPMBUILD@
|
||||||
|
SET_MAKE = @SET_MAKE@
|
||||||
|
SHELL = @SHELL@
|
||||||
|
SRV_CONFDIR = @SRV_CONFDIR@
|
||||||
|
SRV_DATADIR = @SRV_DATADIR@
|
||||||
|
SRV_LOGDIR = @SRV_LOGDIR@
|
||||||
|
SRV_RUNDIR = @SRV_RUNDIR@
|
||||||
|
STRIP = @STRIP@
|
||||||
|
VERSION = @VERSION@
|
||||||
|
XARGS = @XARGS@
|
||||||
|
abs_builddir = @abs_builddir@
|
||||||
|
abs_srcdir = @abs_srcdir@
|
||||||
|
abs_top_builddir = @abs_top_builddir@
|
||||||
|
abs_top_srcdir = @abs_top_srcdir@
|
||||||
|
ac_ct_CC = @ac_ct_CC@
|
||||||
|
am__include = @am__include@
|
||||||
|
am__leading_dot = @am__leading_dot@
|
||||||
|
am__quote = @am__quote@
|
||||||
|
am__rm_f_notfound = @am__rm_f_notfound@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
|
am__xargs_n = @am__xargs_n@
|
||||||
|
bindir = @bindir@
|
||||||
|
build = @build@
|
||||||
|
build_alias = @build_alias@
|
||||||
|
build_cpu = @build_cpu@
|
||||||
|
build_os = @build_os@
|
||||||
|
build_vendor = @build_vendor@
|
||||||
|
builddir = @builddir@
|
||||||
|
datadir = @datadir@
|
||||||
|
datarootdir = @datarootdir@
|
||||||
|
docdir = @docdir@
|
||||||
|
dvidir = @dvidir@
|
||||||
|
exec_prefix = @exec_prefix@
|
||||||
|
host = @host@
|
||||||
|
host_alias = @host_alias@
|
||||||
|
host_cpu = @host_cpu@
|
||||||
|
host_os = @host_os@
|
||||||
|
host_vendor = @host_vendor@
|
||||||
|
htmldir = @htmldir@
|
||||||
|
includedir = @includedir@
|
||||||
|
infodir = @infodir@
|
||||||
|
install_sh = @install_sh@
|
||||||
|
libdir = @libdir@
|
||||||
|
libexecdir = @libexecdir@
|
||||||
|
localedir = @localedir@
|
||||||
|
localstatedir = @localstatedir@
|
||||||
|
mandir = @mandir@
|
||||||
|
mkdir_p = @mkdir_p@
|
||||||
|
oldincludedir = @oldincludedir@
|
||||||
|
pdfdir = @pdfdir@
|
||||||
|
prefix = @prefix@
|
||||||
|
program_transform_name = @program_transform_name@
|
||||||
|
psdir = @psdir@
|
||||||
|
runstatedir = @runstatedir@
|
||||||
|
sbindir = @sbindir@
|
||||||
|
sharedstatedir = @sharedstatedir@
|
||||||
|
srcdir = @srcdir@
|
||||||
|
srv_confdir = @srv_confdir@
|
||||||
|
srv_datadir = @srv_datadir@
|
||||||
|
srv_devel_mode = @srv_devel_mode@
|
||||||
|
srv_logdir = @srv_logdir@
|
||||||
|
srv_name = @srv_name@
|
||||||
|
srv_rundir = @srv_rundir@
|
||||||
|
srv_sbindir = @srv_sbindir@
|
||||||
|
sysconfdir = @sysconfdir@
|
||||||
|
target_alias = @target_alias@
|
||||||
|
top_build_prefix = @top_build_prefix@
|
||||||
|
top_builddir = @top_builddir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
AUTOMAKE_OPTIONS = foreign no-dependencies no-installinfo
|
||||||
|
SUFFIXES = .go
|
||||||
|
mbased_SOURCES = cmd/mbased/main.go
|
||||||
|
mbasedump_SOURCES = cmd/mbasedump/maindump.go
|
||||||
|
mbaserestore_SOURCES = cmd/mbaserestore/mainrestore.go
|
||||||
|
mbasectl_SOURCES = cmd/mbasectl/main.go \
|
||||||
|
cmd/mbasectl/account.go \
|
||||||
|
cmd/mbasectl/grant.go \
|
||||||
|
cmd/mbasectl/dump.go
|
||||||
|
|
||||||
|
mbaseadmin_SOURCES = cmd/mbaseadmin/main.go \
|
||||||
|
cmd/mbaseadmin/account.go \
|
||||||
|
cmd/mbaseadmin/grant.go
|
||||||
|
|
||||||
|
EXTRA_mbased_SOURCES =
|
||||||
|
EXTRA_DIST = \
|
||||||
|
Changelog.txt \
|
||||||
|
Containerfile \
|
||||||
|
etc/mbase/mbased.yaml \
|
||||||
|
.gitignore \
|
||||||
|
go.mod \
|
||||||
|
go.sum \
|
||||||
|
proto/cmctl.proto \
|
||||||
|
README.md \
|
||||||
|
test/account_test.go \
|
||||||
|
test/dump_test.go \
|
||||||
|
test/hello_test.go \
|
||||||
|
test/Makefile.am \
|
||||||
|
test/Makefile.in \
|
||||||
|
test/server.go \
|
||||||
|
test/support.go \
|
||||||
|
vendor/*
|
||||||
|
|
||||||
|
GENDIR = pkg/mbctl
|
||||||
|
PROTOSRC = proto/mbctl.proto
|
||||||
|
SYSTEMD_LIBDIR = /lib/systemd/system
|
||||||
|
FREEBSD_LOCALBASE = /usr/local
|
||||||
|
FREEBSD_RCDIR = $(FREEBSD_LOCALBASE)/etc/rc.d
|
||||||
|
LINUX_SYSTEMDDIR = /lib/systemd/system
|
||||||
|
all: all-am
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
.SUFFIXES: .go
|
||||||
|
am--refresh: Makefile
|
||||||
|
@:
|
||||||
|
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||||
|
@for dep in $?; do \
|
||||||
|
case '$(am__configure_deps)' in \
|
||||||
|
*$$dep*) \
|
||||||
|
echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
|
||||||
|
$(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
|
||||||
|
&& exit 0; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
|
||||||
|
$(am__cd) $(top_srcdir) && \
|
||||||
|
$(AUTOMAKE) --foreign Makefile
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
|
@case '$?' in \
|
||||||
|
*config.status*) \
|
||||||
|
echo ' $(SHELL) ./config.status'; \
|
||||||
|
$(SHELL) ./config.status;; \
|
||||||
|
*) \
|
||||||
|
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
|
||||||
|
esac;
|
||||||
|
|
||||||
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||||
|
$(SHELL) ./config.status --recheck
|
||||||
|
|
||||||
|
$(top_srcdir)/configure: $(am__configure_deps)
|
||||||
|
$(am__cd) $(srcdir) && $(AUTOCONF)
|
||||||
|
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||||
|
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
|
||||||
|
$(am__aclocal_m4_deps):
|
||||||
|
app/config/variant.go: $(top_builddir)/config.status $(top_srcdir)/app/config/variant.go.in
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $@
|
||||||
|
initrc/mbased.service: $(top_builddir)/config.status $(top_srcdir)/initrc/mbased.service.in
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $@
|
||||||
|
initrc/mbased: $(top_builddir)/config.status $(top_srcdir)/initrc/mbased.in
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $@
|
||||||
|
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||||
|
if test -n "$$list"; then \
|
||||||
|
echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
|
||||||
|
$(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
|
||||||
|
fi; \
|
||||||
|
for p in $$list; do echo "$$p $$p"; done | \
|
||||||
|
sed 's/$(EXEEXT)$$//' | \
|
||||||
|
while read p p1; do if test -f $$p \
|
||||||
|
; then echo "$$p"; echo "$$p"; else :; fi; \
|
||||||
|
done | \
|
||||||
|
sed -e 'p;s,.*/,,;n;h' \
|
||||||
|
-e 's|.*|.|' \
|
||||||
|
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
|
||||||
|
sed 'N;N;N;s,\n, ,g' | \
|
||||||
|
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
|
||||||
|
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
|
||||||
|
if ($$2 == $$4) files[d] = files[d] " " $$1; \
|
||||||
|
else { print "f", $$3 "/" $$4, $$1; } } \
|
||||||
|
END { for (d in files) print "f", d, files[d] }' | \
|
||||||
|
while read type dir files; do \
|
||||||
|
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
|
||||||
|
test -z "$$files" || { \
|
||||||
|
echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
|
||||||
|
$(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
|
||||||
|
} \
|
||||||
|
; done
|
||||||
|
|
||||||
|
uninstall-binPROGRAMS:
|
||||||
|
@$(NORMAL_UNINSTALL)
|
||||||
|
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||||
|
files=`for p in $$list; do echo "$$p"; done | \
|
||||||
|
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
|
||||||
|
-e 's/$$/$(EXEEXT)/' \
|
||||||
|
`; \
|
||||||
|
test -n "$$list" || exit 0; \
|
||||||
|
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
|
||||||
|
cd "$(DESTDIR)$(bindir)" && $(am__rm_f) $$files
|
||||||
|
|
||||||
|
clean-binPROGRAMS:
|
||||||
|
-$(am__rm_f) $(bin_PROGRAMS)
|
||||||
|
install-sbinPROGRAMS: $(sbin_PROGRAMS)
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
|
||||||
|
if test -n "$$list"; then \
|
||||||
|
echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
|
||||||
|
$(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
|
||||||
|
fi; \
|
||||||
|
for p in $$list; do echo "$$p $$p"; done | \
|
||||||
|
sed 's/$(EXEEXT)$$//' | \
|
||||||
|
while read p p1; do if test -f $$p \
|
||||||
|
; then echo "$$p"; echo "$$p"; else :; fi; \
|
||||||
|
done | \
|
||||||
|
sed -e 'p;s,.*/,,;n;h' \
|
||||||
|
-e 's|.*|.|' \
|
||||||
|
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
|
||||||
|
sed 'N;N;N;s,\n, ,g' | \
|
||||||
|
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
|
||||||
|
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
|
||||||
|
if ($$2 == $$4) files[d] = files[d] " " $$1; \
|
||||||
|
else { print "f", $$3 "/" $$4, $$1; } } \
|
||||||
|
END { for (d in files) print "f", d, files[d] }' | \
|
||||||
|
while read type dir files; do \
|
||||||
|
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
|
||||||
|
test -z "$$files" || { \
|
||||||
|
echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
|
||||||
|
$(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
|
||||||
|
} \
|
||||||
|
; done
|
||||||
|
|
||||||
|
uninstall-sbinPROGRAMS:
|
||||||
|
@$(NORMAL_UNINSTALL)
|
||||||
|
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
|
||||||
|
files=`for p in $$list; do echo "$$p"; done | \
|
||||||
|
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
|
||||||
|
-e 's/$$/$(EXEEXT)/' \
|
||||||
|
`; \
|
||||||
|
test -n "$$list" || exit 0; \
|
||||||
|
echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
|
||||||
|
cd "$(DESTDIR)$(sbindir)" && $(am__rm_f) $$files
|
||||||
|
|
||||||
|
clean-sbinPROGRAMS:
|
||||||
|
-$(am__rm_f) $(sbin_PROGRAMS)
|
||||||
|
|
||||||
|
mostlyclean-compile:
|
||||||
|
-rm -f *.$(OBJEXT)
|
||||||
|
|
||||||
|
distclean-compile:
|
||||||
|
-rm -f *.tab.c
|
||||||
|
|
||||||
|
ID: $(am__tagged_files)
|
||||||
|
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||||
|
tags: tags-am
|
||||||
|
TAGS: tags
|
||||||
|
|
||||||
|
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||||
|
set x; \
|
||||||
|
here=`pwd`; \
|
||||||
|
$(am__define_uniq_tagged_files); \
|
||||||
|
shift; \
|
||||||
|
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||||
|
test -n "$$unique" || unique=$$empty_fix; \
|
||||||
|
if test $$# -gt 0; then \
|
||||||
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
"$$@" $$unique; \
|
||||||
|
else \
|
||||||
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
$$unique; \
|
||||||
|
fi; \
|
||||||
|
fi
|
||||||
|
ctags: ctags-am
|
||||||
|
|
||||||
|
CTAGS: ctags
|
||||||
|
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||||
|
$(am__define_uniq_tagged_files); \
|
||||||
|
test -z "$(CTAGS_ARGS)$$unique" \
|
||||||
|
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||||
|
$$unique
|
||||||
|
|
||||||
|
GTAGS:
|
||||||
|
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||||
|
&& $(am__cd) $(top_srcdir) \
|
||||||
|
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||||
|
cscope: cscope.files
|
||||||
|
test ! -s cscope.files \
|
||||||
|
|| $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
|
||||||
|
clean-cscope:
|
||||||
|
-rm -f cscope.files
|
||||||
|
cscope.files: clean-cscope cscopelist
|
||||||
|
cscopelist: cscopelist-am
|
||||||
|
|
||||||
|
cscopelist-am: $(am__tagged_files)
|
||||||
|
list='$(am__tagged_files)'; \
|
||||||
|
case "$(srcdir)" in \
|
||||||
|
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||||
|
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||||
|
esac; \
|
||||||
|
for i in $$list; do \
|
||||||
|
if test -f "$$i"; then \
|
||||||
|
echo "$(subdir)/$$i"; \
|
||||||
|
else \
|
||||||
|
echo "$$sdir/$$i"; \
|
||||||
|
fi; \
|
||||||
|
done >> $(top_builddir)/cscope.files
|
||||||
|
|
||||||
|
distclean-tags:
|
||||||
|
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||||
|
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
|
||||||
|
distdir: $(BUILT_SOURCES)
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||||
|
|
||||||
|
distdir-am: $(DISTFILES)
|
||||||
|
$(am__remove_distdir)
|
||||||
|
$(AM_V_at)$(MKDIR_P) "$(distdir)"
|
||||||
|
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
list='$(DISTFILES)'; \
|
||||||
|
dist_files=`for file in $$list; do echo $$file; done | \
|
||||||
|
sed -e "s|^$$srcdirstrip/||;t" \
|
||||||
|
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||||
|
case $$dist_files in \
|
||||||
|
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||||
|
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||||
|
sort -u` ;; \
|
||||||
|
esac; \
|
||||||
|
for file in $$dist_files; do \
|
||||||
|
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||||
|
if test -d $$d/$$file; then \
|
||||||
|
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||||
|
if test -d "$(distdir)/$$file"; then \
|
||||||
|
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||||
|
fi; \
|
||||||
|
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||||
|
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||||
|
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||||
|
fi; \
|
||||||
|
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||||
|
else \
|
||||||
|
test -f "$(distdir)/$$file" \
|
||||||
|
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||||
|
|| exit 1; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
-test -n "$(am__skip_mode_fix)" \
|
||||||
|
|| find "$(distdir)" -type d ! -perm -755 \
|
||||||
|
-exec chmod u+rwx,go+rx {} \; -o \
|
||||||
|
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
|
||||||
|
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
|
||||||
|
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
||||||
|
|| chmod -R a+r "$(distdir)"
|
||||||
|
dist-gzip: distdir
|
||||||
|
tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-bzip2: distdir
|
||||||
|
tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-lzip: distdir
|
||||||
|
tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-xz: distdir
|
||||||
|
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-zstd: distdir
|
||||||
|
tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-tarZ: distdir
|
||||||
|
@echo WARNING: "Support for distribution archives compressed with" \
|
||||||
|
"legacy program 'compress' is deprecated." >&2
|
||||||
|
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
|
||||||
|
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-shar: distdir
|
||||||
|
@echo WARNING: "Support for shar distribution archives is" \
|
||||||
|
"deprecated." >&2
|
||||||
|
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
|
||||||
|
shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-zip: distdir
|
||||||
|
-rm -f $(distdir).zip
|
||||||
|
zip -rq $(distdir).zip $(distdir)
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist dist-all:
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
# This target untars the dist file and tries a VPATH configuration. Then
|
||||||
|
# it guarantees that the distribution is self-contained by making another
|
||||||
|
# tarfile.
|
||||||
|
distcheck: dist
|
||||||
|
case '$(DIST_ARCHIVES)' in \
|
||||||
|
*.tar.gz*) \
|
||||||
|
eval GZIP= gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
|
||||||
|
*.tar.bz2*) \
|
||||||
|
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
|
||||||
|
*.tar.lz*) \
|
||||||
|
lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
|
||||||
|
*.tar.xz*) \
|
||||||
|
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
|
||||||
|
*.tar.Z*) \
|
||||||
|
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
||||||
|
*.shar.gz*) \
|
||||||
|
eval GZIP= gzip -dc $(distdir).shar.gz | unshar ;;\
|
||||||
|
*.zip*) \
|
||||||
|
unzip $(distdir).zip ;;\
|
||||||
|
*.tar.zst*) \
|
||||||
|
zstd -dc $(distdir).tar.zst | $(am__untar) ;;\
|
||||||
|
esac
|
||||||
|
chmod -R a-w $(distdir)
|
||||||
|
chmod u+w $(distdir)
|
||||||
|
mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
|
||||||
|
chmod a-w $(distdir)
|
||||||
|
test -d $(distdir)/_build || exit 0; \
|
||||||
|
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
|
||||||
|
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
|
||||||
|
&& am__cwd=`pwd` \
|
||||||
|
&& $(am__cd) $(distdir)/_build/sub \
|
||||||
|
&& ../../configure \
|
||||||
|
$(AM_DISTCHECK_CONFIGURE_FLAGS) \
|
||||||
|
$(DISTCHECK_CONFIGURE_FLAGS) \
|
||||||
|
--srcdir=../.. --prefix="$$dc_install_base" \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) check \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) install \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
|
||||||
|
distuninstallcheck \
|
||||||
|
&& chmod -R a-w "$$dc_install_base" \
|
||||||
|
&& ({ \
|
||||||
|
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
|
||||||
|
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
|
||||||
|
} || { rm -rf "$$dc_destdir"; exit 1; }) \
|
||||||
|
&& rm -rf "$$dc_destdir" \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) dist \
|
||||||
|
&& rm -rf $(DIST_ARCHIVES) \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
|
||||||
|
&& cd "$$am__cwd" \
|
||||||
|
|| exit 1
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
@(echo "$(distdir) archives ready for distribution: "; \
|
||||||
|
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
|
||||||
|
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
|
||||||
|
distuninstallcheck:
|
||||||
|
@test -n '$(distuninstallcheck_dir)' || { \
|
||||||
|
echo 'ERROR: trying to run $@ with an empty' \
|
||||||
|
'$$(distuninstallcheck_dir)' >&2; \
|
||||||
|
exit 1; \
|
||||||
|
}; \
|
||||||
|
$(am__cd) '$(distuninstallcheck_dir)' || { \
|
||||||
|
echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
|
||||||
|
exit 1; \
|
||||||
|
}; \
|
||||||
|
test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
|
||||||
|
|| { echo "ERROR: files left after uninstall:" ; \
|
||||||
|
if test -n "$(DESTDIR)"; then \
|
||||||
|
echo " (check DESTDIR support)"; \
|
||||||
|
fi ; \
|
||||||
|
$(distuninstallcheck_listfiles) ; \
|
||||||
|
exit 1; } >&2
|
||||||
|
distcleancheck: distclean
|
||||||
|
@if test '$(srcdir)' = . ; then \
|
||||||
|
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
|
||||||
|
exit 1 ; \
|
||||||
|
fi
|
||||||
|
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|
||||||
|
|| { echo "ERROR: files left in build directory after distclean:" ; \
|
||||||
|
$(distcleancheck_listfiles) ; \
|
||||||
|
exit 1; } >&2
|
||||||
|
check-am: all-am
|
||||||
|
check: check-am
|
||||||
|
all-am: Makefile $(PROGRAMS)
|
||||||
|
installdirs:
|
||||||
|
for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)"; do \
|
||||||
|
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||||
|
done
|
||||||
|
install: install-am
|
||||||
|
install-exec: install-exec-am
|
||||||
|
install-data: install-data-am
|
||||||
|
uninstall: uninstall-am
|
||||||
|
|
||||||
|
install-am: all-am
|
||||||
|
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||||
|
|
||||||
|
installcheck: installcheck-am
|
||||||
|
install-strip:
|
||||||
|
if test -z '$(STRIP)'; then \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
install; \
|
||||||
|
else \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||||
|
fi
|
||||||
|
mostlyclean-generic:
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
-$(am__rm_f) $(CONFIG_CLEAN_FILES)
|
||||||
|
-test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES)
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
@echo "This command is intended for maintainers to use"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
clean: clean-am
|
||||||
|
|
||||||
|
clean-am: clean-binPROGRAMS clean-generic clean-local \
|
||||||
|
clean-sbinPROGRAMS mostlyclean-am
|
||||||
|
|
||||||
|
distclean: distclean-am
|
||||||
|
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||||
|
-rm -f Makefile
|
||||||
|
distclean-am: clean-am distclean-compile distclean-generic \
|
||||||
|
distclean-local distclean-tags
|
||||||
|
|
||||||
|
dvi: dvi-am
|
||||||
|
|
||||||
|
dvi-am:
|
||||||
|
|
||||||
|
html: html-am
|
||||||
|
|
||||||
|
html-am:
|
||||||
|
|
||||||
|
info: info-am
|
||||||
|
|
||||||
|
info-am:
|
||||||
|
|
||||||
|
install-data-am: install-data-local
|
||||||
|
|
||||||
|
install-dvi: install-dvi-am
|
||||||
|
|
||||||
|
install-dvi-am:
|
||||||
|
|
||||||
|
install-exec-am: install-binPROGRAMS install-sbinPROGRAMS
|
||||||
|
|
||||||
|
install-html: install-html-am
|
||||||
|
|
||||||
|
install-html-am:
|
||||||
|
|
||||||
|
install-info: install-info-am
|
||||||
|
|
||||||
|
install-info-am:
|
||||||
|
|
||||||
|
install-man:
|
||||||
|
|
||||||
|
install-pdf: install-pdf-am
|
||||||
|
|
||||||
|
install-pdf-am:
|
||||||
|
|
||||||
|
install-ps: install-ps-am
|
||||||
|
|
||||||
|
install-ps-am:
|
||||||
|
|
||||||
|
installcheck-am:
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-am
|
||||||
|
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||||
|
-rm -rf $(top_srcdir)/autom4te.cache
|
||||||
|
-rm -f Makefile
|
||||||
|
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-am
|
||||||
|
|
||||||
|
mostlyclean-am: mostlyclean-compile mostlyclean-generic
|
||||||
|
|
||||||
|
pdf: pdf-am
|
||||||
|
|
||||||
|
pdf-am:
|
||||||
|
|
||||||
|
ps: ps-am
|
||||||
|
|
||||||
|
ps-am:
|
||||||
|
|
||||||
|
uninstall-am: uninstall-binPROGRAMS uninstall-sbinPROGRAMS
|
||||||
|
|
||||||
|
.MAKE: install-am install-strip
|
||||||
|
|
||||||
|
.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-am clean \
|
||||||
|
clean-binPROGRAMS clean-cscope clean-generic clean-local \
|
||||||
|
clean-sbinPROGRAMS cscope cscopelist-am ctags ctags-am dist \
|
||||||
|
dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \
|
||||||
|
dist-xz dist-zip dist-zstd distcheck distclean \
|
||||||
|
distclean-compile distclean-generic distclean-local \
|
||||||
|
distclean-tags distcleancheck distdir distuninstallcheck dvi \
|
||||||
|
dvi-am html html-am info info-am install install-am \
|
||||||
|
install-binPROGRAMS install-data install-data-am \
|
||||||
|
install-data-local install-dvi install-dvi-am install-exec \
|
||||||
|
install-exec-am install-html install-html-am install-info \
|
||||||
|
install-info-am install-man install-pdf install-pdf-am \
|
||||||
|
install-ps install-ps-am install-sbinPROGRAMS install-strip \
|
||||||
|
installcheck installcheck-am installdirs maintainer-clean \
|
||||||
|
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||||
|
mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
|
||||||
|
uninstall-am uninstall-binPROGRAMS uninstall-sbinPROGRAMS
|
||||||
|
|
||||||
|
.PRECIOUS: Makefile
|
||||||
|
|
||||||
|
mbased$(EXEEXT): $(mbased_SOURCES) $(EXTRA_mbased_SOURCES)
|
||||||
|
env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o mbased$(EXEEXT) $(mbased_SOURCES)
|
||||||
|
mbasedump$(EXEEXT): $(mbasedump_SOURCES) $(EXTRA_mbased_SOURCES)
|
||||||
|
env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o mbasedump$(EXEEXT) $(mbasedump_SOURCES)
|
||||||
|
mbaserestore$(EXEEXT): $(mbaserestore_SOURCES) $(EXTRA_mbased_SOURCES)
|
||||||
|
env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o mbaserestore$(EXEEXT) $(mbaserestore_SOURCES)
|
||||||
|
|
||||||
|
mbasectl$(EXEEXT): $(mbasectl_SOURCES) $(EXTRA_mbased_SOURCES)
|
||||||
|
env CGO_ENABLED=0 $(GO) build $(GOFLAGS) -o mbasectl$(EXEEXT) $(mbasectl_SOURCES)
|
||||||
|
|
||||||
|
mbaseadmin$(EXEEXT): $(mbaseadmin_SOURCES) $(EXTRA_mbased_SOURCES)
|
||||||
|
env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o mbaseadmin$(EXEEXT) $(mbaseadmin_SOURCES)
|
||||||
|
|
||||||
|
rpc:
|
||||||
|
mkdir -p $(GENDIR)
|
||||||
|
$(PROTOC) --proto_path=proto --go_out=$(GENDIR) --go-grpc_out=$(GENDIR) $(PROTOSRC)
|
||||||
|
|
||||||
|
install-data-local:
|
||||||
|
test -z $(DESTDIR)$(SRV_CONFDIR) || $(MKDIR_P) $(DESTDIR)$(SRV_CONFDIR)
|
||||||
|
test -z $(DESTDIR)$(SRV_LOGDIR) || $(MKDIR_P) $(DESTDIR)$(SRV_LOGDIR)
|
||||||
|
test -z $(DESTDIR)$(SRV_RUNDIR) || $(MKDIR_P) $(DESTDIR)$(SRV_RUNDIR)
|
||||||
|
test -z $(DESTDIR)$(SRV_DATADIR) || $(MKDIR_P) $(DESTDIR)$(SRV_DATADIR)
|
||||||
|
test -z $(DESTDIR)$(SYSTEMD_LIBDIR) || $(MKDIR_P) $(DESTDIR)$(SYSTEMD_LIBDIR)
|
||||||
|
@FREEBSD_OS_TRUE@ test -z $(DESTDIR)$(FREEBSD_RCDIR) || $(MKDIR_P) $(DESTDIR)$(FREEBSD_RCDIR)
|
||||||
|
@FREEBSD_OS_TRUE@ $(INSTALL_DATA) initrc/mbased $(DESTDIR)$(FREEBSD_RCDIR)
|
||||||
|
@FREEBSD_OS_TRUE@ chmod a+x $(DESTDIR)$(FREEBSD_RCDIR)/mbased
|
||||||
|
@LINUX_OS_TRUE@@SYSTEMD_TRUE@ test -z $(DESTDIR)$(LINUX_SYSTEMDDIR) || $(MKDIR_P) $(DESTDIR)$(LINUX_SYSTEMDDIR)
|
||||||
|
@LINUX_OS_TRUE@@SYSTEMD_TRUE@ $(INSTALL_DATA) initrc/mbased.service $(DESTDIR)$(LINUX_SYSTEMDDIR)
|
||||||
|
|
||||||
|
format:
|
||||||
|
for dir in $$(find app pkg cmd -type d); do \
|
||||||
|
(cd $$dir && $(GO) fmt .); \
|
||||||
|
done
|
||||||
|
|
||||||
|
run:
|
||||||
|
test -z $(DESTDIR)$(SRV_LOGDIR) || $(MKDIR_P) $(DESTDIR)$(SRV_LOGDIR)
|
||||||
|
test -z $(DESTDIR)$(SRV_RUNDIR) || $(MKDIR_P) $(DESTDIR)$(SRV_RUNDIR)
|
||||||
|
test -z $(DESTDIR)$(SRV_DATADIR) || $(MKDIR_P) $(DESTDIR)$(SRV_DATADIR)
|
||||||
|
env CGO_ENABLED=1 $(GO) run $(GOFLAGS) ./cmd/mbased/... --daemon=false
|
||||||
|
|
||||||
|
distclean-local: clean
|
||||||
|
rm -rf autom4te.cache
|
||||||
|
|
||||||
|
clean-local:
|
||||||
|
rm -f */*/*~
|
||||||
|
rm -f */*~
|
||||||
|
rm -f *~
|
||||||
|
rm -f cmd/mbaseadmin/mbaseadmin
|
||||||
|
rm -f cmd/mbasectl/mbasectl
|
||||||
|
rm -f cmd/mbased/mbased
|
||||||
|
rm -f cmd/mbasedump/mbasedump
|
||||||
|
rm -f cmd/mbaselocal/mbaselocal
|
||||||
|
rm -f cmd/mbaserestore/mbaserestore
|
||||||
|
rm -rf autom4te.cache
|
||||||
|
rm -rf tmp/
|
||||||
|
|
||||||
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
.NOEXPORT:
|
||||||
|
|
||||||
|
# Tell GNU make to disable its built-in pattern rules.
|
||||||
|
%:: %,v
|
||||||
|
%:: RCS/%,v
|
||||||
|
%:: RCS/%
|
||||||
|
%:: s.%
|
||||||
|
%:: SCCS/s.%
|
||||||
Vendored
+1307
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,152 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"mbase/pkg/client"
|
||||||
|
|
||||||
|
"go.yaml.in/yaml/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultHostname = "localhost"
|
||||||
|
|
||||||
|
configFilename = "maind.yaml"
|
||||||
|
logFilename = "maind.log"
|
||||||
|
pidFilename = "maind.pid"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
buildVersion = "NONE"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Networks struct {
|
||||||
|
Enabled []string `json:"enabled" yaml:"enabled"`
|
||||||
|
Disabled []string `json:"disabled" yaml:"disabled"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServiceConfig struct {
|
||||||
|
Portnum uint32 `json:"port" yaml:"port"`
|
||||||
|
Address string `json:"address" yaml:"address"`
|
||||||
|
Protocol string `json:"protocol" yaml:"protocol"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
PackageVersion string `json:"packageVersion" yaml:"packageVersion"`
|
||||||
|
Service ServiceConfig `json:"service" yaml:"service"`
|
||||||
|
Networks Networks `json:"networks" yaml:"networks"`
|
||||||
|
Hostname string `json:"hostname" yaml:"hostname"`
|
||||||
|
Debug bool `json:"debug" yaml:"debug"`
|
||||||
|
Build string `json:"build" yaml:"build"`
|
||||||
|
LogPath string `json:"logfile" yaml:"logfile"`
|
||||||
|
RunPath string `json:"runfile" yaml:"runfile"`
|
||||||
|
DataDir string `json:"datadir" yaml:"datadir"`
|
||||||
|
Daemon bool `json:"daemon" yaml:"daemon"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
defaultEnabledNetworks = []string{"0.0.0.0/0", "::/0"}
|
||||||
|
defaultDisabledNetworks = []string{}
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultServiceAddress = "0.0.0.0"
|
||||||
|
defaultServiceProtocol = "tcp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewConfig() *Config {
|
||||||
|
conf := &Config{
|
||||||
|
Service: ServiceConfig{
|
||||||
|
Portnum: client.DefaultPort,
|
||||||
|
Address: defaultServiceAddress,
|
||||||
|
Protocol: defaultServiceProtocol,
|
||||||
|
},
|
||||||
|
DataDir: datadirPath,
|
||||||
|
Debug: false,
|
||||||
|
Hostname: defaultHostname,
|
||||||
|
Build: buildVersion,
|
||||||
|
Daemon: true,
|
||||||
|
PackageVersion: packageVersion,
|
||||||
|
|
||||||
|
Networks: Networks{
|
||||||
|
Enabled: defaultEnabledNetworks,
|
||||||
|
Disabled: defaultDisabledNetworks,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
conf.LogPath = filepath.Join(logdirPath, logFilename)
|
||||||
|
conf.RunPath = filepath.Join(rundirPath, pidFilename)
|
||||||
|
return conf
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conf *Config) ReadFile() error {
|
||||||
|
var err error
|
||||||
|
confPath := filepath.Join(confdirPath, configFilename)
|
||||||
|
confBytes, err := os.ReadFile(confPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = yaml.Unmarshal(confBytes, conf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
conf.Normalize()
|
||||||
|
err = conf.Validate()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conf *Config) ReadEnv() error {
|
||||||
|
var err error
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conf *Config) ReadOpts() error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
exeName := filepath.Base(os.Args[0])
|
||||||
|
|
||||||
|
flag.BoolVar(&conf.Daemon, "daemon", conf.Daemon, "run as daemon")
|
||||||
|
flag.BoolVar(&conf.Debug, "debug", conf.Debug, "on debug mode")
|
||||||
|
|
||||||
|
help := func() {
|
||||||
|
fmt.Println("")
|
||||||
|
fmt.Printf("Usage: %s [option]\n", exeName)
|
||||||
|
fmt.Println("")
|
||||||
|
fmt.Println("Options:")
|
||||||
|
flag.PrintDefaults()
|
||||||
|
fmt.Println("")
|
||||||
|
}
|
||||||
|
flag.Usage = help
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conf *Config) String() (string, error) {
|
||||||
|
var err error
|
||||||
|
var res string
|
||||||
|
yamlBytes, err := yaml.Marshal(conf)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
res = string(yamlBytes)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conf *Config) Normalize() {
|
||||||
|
if conf.Service.Portnum == 0 {
|
||||||
|
conf.Service.Portnum = client.DefaultPort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conf *Config) Validate() error {
|
||||||
|
var err []error
|
||||||
|
return errors.Join(err...)
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
const (
|
||||||
|
confdirPath = "@srv_confdir@"
|
||||||
|
rundirPath = "@srv_rundir@"
|
||||||
|
logdirPath = "@srv_logdir@"
|
||||||
|
datadirPath = "@srv_datadir@"
|
||||||
|
packageVersion = "@PACKAGE_VERSION@"
|
||||||
|
)
|
||||||
|
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"mbase/app/descriptor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (db *Database) InsertAccount(ctx context.Context, account *descriptor.Account) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
request := `INSERT INTO account(id, username, passhash, disabled, created_at, updated_at)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6)`
|
||||||
|
_, err = db.db.Exec(request, account.ID, account.Username, account.Passhash,
|
||||||
|
account.Disabled, account.CreatedAt, account.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) UpdateAccountByID(ctx context.Context, accountID int64, account *descriptor.Account) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
request := `UPDATE account SET username = $1, passhash = $2, disabled = $3, updated_at = $4 WHERE id = $5`
|
||||||
|
_, err = db.db.Exec(request, account.Username, account.Passhash, account.Disabled, account.UpdatedAt, accountID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) ReducedListAccounts(ctx context.Context) ([]descriptor.Account, error) {
|
||||||
|
var err error
|
||||||
|
request := `SELECT id, username, disabled, created_at, updated_at FROM account`
|
||||||
|
res := make([]descriptor.Account, 0)
|
||||||
|
err = db.db.Select(&res, request)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) CompletedListAccounts(ctx context.Context) ([]descriptor.Account, error) {
|
||||||
|
var err error
|
||||||
|
request := `SELECT * FROM account`
|
||||||
|
res := make([]descriptor.Account, 0)
|
||||||
|
err = db.db.Select(&res, request)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) GetAccountByID(ctx context.Context, accountID int64) (bool, *descriptor.Account, error) {
|
||||||
|
var err error
|
||||||
|
var res *descriptor.Account
|
||||||
|
var exists bool
|
||||||
|
request := `SELECT id, username, passhash, disabled, created_at, updated_at
|
||||||
|
FROM account WHERE id = $1 LiMIT 1`
|
||||||
|
dbRes := make([]descriptor.Account, 0)
|
||||||
|
err = db.db.Select(&dbRes, request, accountID)
|
||||||
|
if err != nil {
|
||||||
|
return exists, res, err
|
||||||
|
}
|
||||||
|
if len(dbRes) == 0 {
|
||||||
|
return exists, res, err
|
||||||
|
}
|
||||||
|
exists = true
|
||||||
|
res = &dbRes[0]
|
||||||
|
return exists, res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) GetAccountByUsername(ctx context.Context, username string) (bool, *descriptor.Account, error) {
|
||||||
|
var err error
|
||||||
|
var res *descriptor.Account
|
||||||
|
var exists bool
|
||||||
|
request := `SELECT id, username, passhash, disabled, created_at, updated_at
|
||||||
|
FROM account WHERE username = $1 LIMIT 1`
|
||||||
|
dbRes := make([]descriptor.Account, 0)
|
||||||
|
err = db.db.Select(&dbRes, request, username)
|
||||||
|
if err != nil {
|
||||||
|
return exists, res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(dbRes) == 0 {
|
||||||
|
return false, res, err
|
||||||
|
}
|
||||||
|
exists = true
|
||||||
|
res = &dbRes[0]
|
||||||
|
return exists, res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) DeleteAccountByID(ctx context.Context, accountID int64) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
request := `DELETE FROM account WHERE id = $1`
|
||||||
|
_, err = db.db.Exec(request, accountID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) DeleteAccountByUsername(ctx context.Context, username string) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
request := `DELETE FROM account WHERE username = $1`
|
||||||
|
_, err = db.db.Exec(request, username)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"mbase/pkg/logger"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
)
|
||||||
|
|
||||||
|
const schema = `
|
||||||
|
--- DROP TABLE IF EXISTS issuer;
|
||||||
|
CREATE TABLE IF NOT EXISTS issuer (
|
||||||
|
id INT NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
cert TEXT NOT NULL,
|
||||||
|
key TEXT,
|
||||||
|
signer_id INT NOT NULL,
|
||||||
|
signer_name TEXT NOT NULL,
|
||||||
|
revoked BOOL
|
||||||
|
);
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS issuer_index01
|
||||||
|
ON issuer(id);
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS issuer_index02
|
||||||
|
ON issuer(name);
|
||||||
|
|
||||||
|
--- DROP TABLE IF EXISTS service;
|
||||||
|
CREATE TABLE IF NOT EXISTS service (
|
||||||
|
id INT NOT NULL,
|
||||||
|
issuer_id INT NOT NULL,
|
||||||
|
issuer_name TEXT NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
cert TEXT NOT NULL,
|
||||||
|
key TEXT NOT NULL,
|
||||||
|
revoked BOOL
|
||||||
|
);
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS service_index01
|
||||||
|
ON service(id);
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS service_index02
|
||||||
|
ON service(name);
|
||||||
|
|
||||||
|
--- DROP TABLE IF EXISTS account;
|
||||||
|
CREATE TABLE IF NOT EXISTS account (
|
||||||
|
id INT NOT NULL,
|
||||||
|
username TEXT NOT NULL,
|
||||||
|
passhash TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL,
|
||||||
|
updated_at TEXT NOT NULL,
|
||||||
|
disabled BOOL
|
||||||
|
);
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS account_index01
|
||||||
|
ON account(id);
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS account_index02
|
||||||
|
ON account(username);
|
||||||
|
|
||||||
|
|
||||||
|
--- DROP TABLE IF EXISTS grant;
|
||||||
|
CREATE TABLE IF NOT EXISTS grant (
|
||||||
|
id INT NOT NULL,
|
||||||
|
account_id INT NOT NULL,
|
||||||
|
operation TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL
|
||||||
|
);
|
||||||
|
CREATE INDEX IF NOT EXISTS grant_index01
|
||||||
|
ON grant(account_id);
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS grant_index02
|
||||||
|
ON grant(account_id, operation);
|
||||||
|
`
|
||||||
|
|
||||||
|
type Database struct {
|
||||||
|
datapath string
|
||||||
|
db *sqlx.DB
|
||||||
|
log *logger.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDatabase(datapath string) (*Database, error) {
|
||||||
|
var err error
|
||||||
|
db := &Database{
|
||||||
|
datapath: datapath,
|
||||||
|
}
|
||||||
|
db.log = logger.NewLogger("database")
|
||||||
|
return db, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) OpenDatabase() error {
|
||||||
|
var err error
|
||||||
|
dbPath := filepath.Join(db.datapath, "certmanager.db")
|
||||||
|
db.db, err = sqlx.Open("sqlite3", dbPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = db.db.Ping()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) InitDatabase() error {
|
||||||
|
var err error
|
||||||
|
_, err = db.db.Exec(schema)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) CleanDatabase(ctx context.Context) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
request := `
|
||||||
|
DELETE FROM account;
|
||||||
|
DELETE FROM grant;
|
||||||
|
`
|
||||||
|
_, err = db.db.Exec(request)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"mbase/app/descriptor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (db *Database) InsertGrant(ctx context.Context, grant *descriptor.Grant) error {
|
||||||
|
var err error
|
||||||
|
request := `INSERT INTO grant(id, account_id, operation, created_at)
|
||||||
|
VALUES ($1, $2, $3, $4)`
|
||||||
|
_, err = db.db.Exec(request, grant.ID, grant.AccountID, grant.Operation, grant.CreatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) ListGrantsByAccountID(ctx context.Context, accountID int64) ([]descriptor.Grant, error) {
|
||||||
|
var err error
|
||||||
|
request := `SELECT * FROM grant WHERE account_id = $1`
|
||||||
|
res := make([]descriptor.Grant, 0)
|
||||||
|
err = db.db.Select(&res, request, accountID)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) ListGrants(ctx context.Context) ([]descriptor.Grant, error) {
|
||||||
|
var err error
|
||||||
|
request := `SELECT * FROM grant`
|
||||||
|
res := make([]descriptor.Grant, 0)
|
||||||
|
err = db.db.Select(&res, request)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) GetGrant(ctx context.Context, accountID int64, operation string) (bool, *descriptor.Grant, error) {
|
||||||
|
var err error
|
||||||
|
res := &descriptor.Grant{}
|
||||||
|
request := `SELECT * FROM grant WHERE account_id = $1 AND operation = $2 LIMIT 1`
|
||||||
|
dbRes := make([]descriptor.Grant, 0)
|
||||||
|
err = db.db.Select(&dbRes, request, accountID, operation)
|
||||||
|
if err != nil {
|
||||||
|
return false, res, err
|
||||||
|
}
|
||||||
|
if len(dbRes) == 0 {
|
||||||
|
return false, res, err
|
||||||
|
|
||||||
|
}
|
||||||
|
res = &dbRes[0]
|
||||||
|
return true, res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) DeleteGrantByAccountID(ctx context.Context, grantID int64, operation string) error {
|
||||||
|
var err error
|
||||||
|
request := `DELETE FROM grant WHERE account_id = $1 AND operation = $2`
|
||||||
|
_, err = db.db.Exec(request, grantID, operation)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) DeleteAllGrantsForAccountID(ctx context.Context, grantID int64) error {
|
||||||
|
var err error
|
||||||
|
request := `DELETE FROM grant WHERE account_id = $1`
|
||||||
|
_, err = db.db.Exec(request, grantID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package descriptor
|
||||||
|
|
||||||
|
const (
|
||||||
|
GrantModifyUsers = "modifyUsers"
|
||||||
|
GrantModifyDatabase = "modifyDatabase"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Dump struct {
|
||||||
|
Timestamp string `json:"timestamp" yaml:"timestamp"`
|
||||||
|
Accounts []Account `json:"accounts" yaml:"accounts"`
|
||||||
|
Grants []Grant `json:"grants" yaml:"grants"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Account struct {
|
||||||
|
ID int64 `json:"id" yaml:"id" db:"id"`
|
||||||
|
Username string `json:"username" yaml:"username" db:"username"`
|
||||||
|
Passhash string `json:"passhash" yaml:"passhash" db:"passhash"`
|
||||||
|
Disabled bool `json:"disabled" yaml:"disabled" db:"disabled"`
|
||||||
|
CreatedAt string `json:"createdAt" yaml:"createdAt" db:"created_at"`
|
||||||
|
UpdatedAt string `json:"updatedAt" yaml:"updatedAt" db:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Grant struct {
|
||||||
|
ID int64 `json:"id" yaml:"id" db:"id"`
|
||||||
|
AccountID int64 `json:"accountID" yaml:"accountID" db:"account_id"`
|
||||||
|
Operation string `json:"operation" yaml:"operation" db:"operation"`
|
||||||
|
CreatedAt string `json:"createdAt" yaml:"createdAt" db:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
DatabaseInitialized bool `json:"databaseInitialized" yaml:"databaseInitialized"`
|
||||||
|
CreatedAt string `json:"createdAt" yaml:"createdAt"`
|
||||||
|
UpdatedAt string `json:"updatedAt" yaml:"updatedAt"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"mbase/pkg/mbctl"
|
||||||
|
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/metadata"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (hand *Handler) Authentificate(ctx context.Context) (int64, error) {
|
||||||
|
var err error
|
||||||
|
var accountID int64
|
||||||
|
|
||||||
|
meta, _ := metadata.FromIncomingContext(ctx)
|
||||||
|
usernameArr := meta["username"]
|
||||||
|
passwordArr := meta["password"]
|
||||||
|
if len(usernameArr) == 0 || len(passwordArr) == 0 {
|
||||||
|
err := status.Errorf(codes.PermissionDenied, "Empty auth data")
|
||||||
|
return accountID, err
|
||||||
|
}
|
||||||
|
username := meta["username"][0]
|
||||||
|
password := meta["password"][0]
|
||||||
|
validated, accountID, err := hand.lg.ValidateAcount(ctx, username, password)
|
||||||
|
if !validated {
|
||||||
|
err := status.Errorf(codes.PermissionDenied, "Wrong auth data")
|
||||||
|
return accountID, err
|
||||||
|
}
|
||||||
|
return accountID, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hand *Handler) CreateAccount(ctx context.Context, params *mbctl.CreateAccountParams) (*mbctl.CreateAccountResult, error) {
|
||||||
|
var err error
|
||||||
|
hand.log.Debugf("Handle CreateAccount call")
|
||||||
|
res := &mbctl.CreateAccountResult{}
|
||||||
|
accountID, err := hand.Authentificate(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
res, err = hand.lg.CreateAccount(ctx, accountID, params)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hand *Handler) DeleteAccount(ctx context.Context, params *mbctl.DeleteAccountParams) (*mbctl.DeleteAccountResult, error) {
|
||||||
|
var err error
|
||||||
|
hand.log.Debugf("Handle DeleteAccount call")
|
||||||
|
res := &mbctl.DeleteAccountResult{}
|
||||||
|
accountID, err := hand.Authentificate(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
res, err = hand.lg.DeleteAccount(ctx, accountID, params)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hand *Handler) ListAccounts(ctx context.Context, params *mbctl.ListAccountsParams) (*mbctl.ListAccountsResult, error) {
|
||||||
|
var err error
|
||||||
|
hand.log.Debugf("Handle ListAccounts call")
|
||||||
|
res := &mbctl.ListAccountsResult{}
|
||||||
|
accountID, err := hand.Authentificate(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
res, err = hand.lg.ListAccounts(ctx, accountID, params)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hand *Handler) UpdateAccount(ctx context.Context, params *mbctl.UpdateAccountParams) (*mbctl.UpdateAccountResult, error) {
|
||||||
|
var err error
|
||||||
|
hand.log.Debugf("Handle UpdateAccount call")
|
||||||
|
res := &mbctl.UpdateAccountResult{}
|
||||||
|
accountID, err := hand.Authentificate(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
res, err = hand.lg.UpdateAccount(ctx, accountID, params)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"mbase/pkg/mbctl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (hand *Handler) GetDump(ctx context.Context, params *mbctl.GetDumpParams) (*mbctl.GetDumpResult, error) {
|
||||||
|
var err error
|
||||||
|
hand.log.Debugf("Handle GetDump call")
|
||||||
|
res := &mbctl.GetDumpResult{}
|
||||||
|
accountID, err := hand.Authentificate(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
res, err = hand.lg.GetDump(ctx, accountID, params)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hand *Handler) RestoreDump(ctx context.Context, params *mbctl.RestoreDumpParams) (*mbctl.RestoreDumpResult, error) {
|
||||||
|
var err error
|
||||||
|
hand.log.Debugf("Handle GetDump call")
|
||||||
|
res := &mbctl.RestoreDumpResult{}
|
||||||
|
accountID, err := hand.Authentificate(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
res, err = hand.lg.RestoreDump(ctx, accountID, params)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"mbase/pkg/mbctl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (hand *Handler) SetGrant(ctx context.Context, params *mbctl.SetGrantParams) (*mbctl.SetGrantResult, error) {
|
||||||
|
var err error
|
||||||
|
hand.log.Debugf("Handle SetGrant call")
|
||||||
|
res := &mbctl.SetGrantResult{}
|
||||||
|
accountID, err := hand.Authentificate(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
res, err = hand.lg.SetGrant(ctx, accountID, params)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hand *Handler) DeleteGrant(ctx context.Context, params *mbctl.DeleteGrantParams) (*mbctl.DeleteGrantResult, error) {
|
||||||
|
var err error
|
||||||
|
hand.log.Debugf("Handle DeleteGrant call")
|
||||||
|
res := &mbctl.DeleteGrantResult{}
|
||||||
|
accountID, err := hand.Authentificate(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
res, err = hand.lg.DeleteGrant(ctx, accountID, params)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"mbase/app/logic"
|
||||||
|
"mbase/pkg/mbctl"
|
||||||
|
"mbase/pkg/logger"
|
||||||
|
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HandlerConfig struct {
|
||||||
|
Logic *logic.Logic
|
||||||
|
}
|
||||||
|
|
||||||
|
type Handler struct {
|
||||||
|
mbctl.UnimplementedControlServer
|
||||||
|
lg *logic.Logic
|
||||||
|
log *logger.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHandler(conf *HandlerConfig) *Handler {
|
||||||
|
hand := Handler{
|
||||||
|
lg: conf.Logic,
|
||||||
|
}
|
||||||
|
hand.log = logger.NewLogger("ghandler")
|
||||||
|
return &hand
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hand *Handler) Register(gsrv *grpc.Server) {
|
||||||
|
mbctl.RegisterControlServer(gsrv, hand)
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"mbase/pkg/mbctl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (hand *Handler) GetHello(ctx context.Context, params *mbctl.GetHelloParams) (*mbctl.GetHelloResult, error) {
|
||||||
|
var err error
|
||||||
|
hand.log.Debugf("Handle getHello call")
|
||||||
|
res, err := hand.lg.GetHello(ctx, params)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,232 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"mbase/app/descriptor"
|
||||||
|
"mbase/pkg/auxid"
|
||||||
|
"mbase/pkg/auxpwd"
|
||||||
|
"mbase/pkg/mbctl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (lg *Logic) ValidateAcount(ctx context.Context, username, password string) (bool, int64, error) {
|
||||||
|
var err error
|
||||||
|
var accountID int64
|
||||||
|
var valid bool
|
||||||
|
|
||||||
|
lg.WaitRestoring()
|
||||||
|
|
||||||
|
accountExists, accountDescr, err := lg.db.GetAccountByUsername(ctx, username)
|
||||||
|
if !accountExists {
|
||||||
|
err := fmt.Errorf("Account not exists")
|
||||||
|
return valid, accountID, err
|
||||||
|
}
|
||||||
|
if !auxpwd.PasswordMatchCompat([]byte(password), accountDescr.Passhash) {
|
||||||
|
err := fmt.Errorf("Login data mismatch")
|
||||||
|
return valid, accountID, err
|
||||||
|
}
|
||||||
|
valid = true
|
||||||
|
accountID = accountDescr.ID
|
||||||
|
return valid, accountID, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lg *Logic) CreateAccount(ctx context.Context, accountID int64, params *mbctl.CreateAccountParams) (*mbctl.CreateAccountResult, error) {
|
||||||
|
var err error
|
||||||
|
res := &mbctl.CreateAccountResult{}
|
||||||
|
|
||||||
|
lg.WaitDumping()
|
||||||
|
lg.WaitRestoring()
|
||||||
|
|
||||||
|
grantExists, _, err := lg.db.GetGrant(ctx, accountID, descriptor.GrantModifyUsers)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if !grantExists {
|
||||||
|
err := fmt.Errorf("Operation not allowed for the user")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if params.Username == "" {
|
||||||
|
err := fmt.Errorf("Empty username parameters")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.Password == "" {
|
||||||
|
err := fmt.Errorf("Empty password parameter")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
accountExists, _, err := lg.db.GetAccountByUsername(ctx, params.Username)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if accountExists {
|
||||||
|
err := fmt.Errorf("Account with thist name already exists")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
now := time.Now().Format(time.RFC3339)
|
||||||
|
passhash := auxpwd.MakeSHA256Hash([]byte(params.Password))
|
||||||
|
accountDescr := &descriptor.Account{
|
||||||
|
ID: auxid.GenID(),
|
||||||
|
Username: params.Username,
|
||||||
|
Passhash: passhash,
|
||||||
|
Disabled: false,
|
||||||
|
CreatedAt: now,
|
||||||
|
UpdatedAt: now,
|
||||||
|
}
|
||||||
|
err = lg.db.InsertAccount(ctx, accountDescr)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
res.AccountID = accountDescr.ID
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lg *Logic) UpdateAccount(ctx context.Context, accountID int64, params *mbctl.UpdateAccountParams) (*mbctl.UpdateAccountResult, error) {
|
||||||
|
var err error
|
||||||
|
res := &mbctl.UpdateAccountResult{}
|
||||||
|
|
||||||
|
lg.WaitRestoring()
|
||||||
|
lg.WaitDumping()
|
||||||
|
|
||||||
|
grantExists, _, err := lg.db.GetGrant(ctx, accountID, descriptor.GrantModifyUsers)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if !grantExists {
|
||||||
|
err := fmt.Errorf("Operation not allowed for the user")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var accountDescr *descriptor.Account
|
||||||
|
var accountExists bool
|
||||||
|
switch {
|
||||||
|
case params.AccountID != 0:
|
||||||
|
accountExists, accountDescr, err = lg.db.GetAccountByID(ctx, params.AccountID)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
case params.Username != "":
|
||||||
|
accountExists, accountDescr, err = lg.db.GetAccountByUsername(ctx, params.Username)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !accountExists {
|
||||||
|
err := fmt.Errorf("Account with this is or name dont exists")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
now := time.Now().Format(time.RFC3339)
|
||||||
|
if params.NewUsername != "" {
|
||||||
|
accountDescr.UpdatedAt = now
|
||||||
|
accountDescr.Username = params.NewUsername
|
||||||
|
}
|
||||||
|
if params.NewPassword != "" {
|
||||||
|
passhash := auxpwd.MakeSHA256Hash([]byte(params.NewPassword))
|
||||||
|
|
||||||
|
accountDescr.UpdatedAt = now
|
||||||
|
accountDescr.Passhash = passhash
|
||||||
|
}
|
||||||
|
if params.Disabled != accountDescr.Disabled {
|
||||||
|
accountDescr.UpdatedAt = now
|
||||||
|
accountDescr.Disabled = params.Disabled
|
||||||
|
}
|
||||||
|
|
||||||
|
err = lg.db.UpdateAccountByID(ctx, accountDescr.ID, accountDescr)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lg *Logic) DeleteAccount(ctx context.Context, accountID int64, params *mbctl.DeleteAccountParams) (*mbctl.DeleteAccountResult, error) {
|
||||||
|
var err error
|
||||||
|
res := &mbctl.DeleteAccountResult{}
|
||||||
|
|
||||||
|
lg.WaitDumping()
|
||||||
|
lg.WaitRestoring()
|
||||||
|
|
||||||
|
grantExists, _, err := lg.db.GetGrant(ctx, accountID, descriptor.GrantModifyUsers)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if !grantExists {
|
||||||
|
err := fmt.Errorf("Operation not allowed for the user")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var accountDescr *descriptor.Account
|
||||||
|
var accountExists bool
|
||||||
|
switch {
|
||||||
|
case params.AccountID != 0:
|
||||||
|
accountExists, accountDescr, err = lg.db.GetAccountByID(ctx, params.AccountID)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
case params.Username != "":
|
||||||
|
accountExists, accountDescr, err = lg.db.GetAccountByUsername(ctx, params.Username)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !accountExists {
|
||||||
|
err := fmt.Errorf("Account with this is or name dont exists")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = lg.db.DeleteAllGrantsForAccountID(ctx, accountDescr.ID)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
err = lg.db.DeleteAccountByID(ctx, accountDescr.ID)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lg *Logic) ListAccounts(ctx context.Context, accountID int64, params *mbctl.ListAccountsParams) (*mbctl.ListAccountsResult, error) {
|
||||||
|
var err error
|
||||||
|
res := &mbctl.ListAccountsResult{
|
||||||
|
Accounts: make([]*mbctl.AccountShortDescr, 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
lg.WaitRestoring()
|
||||||
|
|
||||||
|
grantExists, _, err := lg.db.GetGrant(ctx, accountID, descriptor.GrantModifyUsers)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if !grantExists {
|
||||||
|
err := fmt.Errorf("Operation not allowed for the user")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
accountDescrs, err := lg.db.ReducedListAccounts(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
for _, accountDescr := range accountDescrs {
|
||||||
|
accountShortDescr := &mbctl.AccountShortDescr{
|
||||||
|
Username: accountDescr.Username,
|
||||||
|
Disabled: accountDescr.Disabled,
|
||||||
|
CreatedAt: accountDescr.CreatedAt,
|
||||||
|
UpdatedAt: accountDescr.UpdatedAt,
|
||||||
|
Grants: make([]*mbctl.GrantShortDescr, 0),
|
||||||
|
}
|
||||||
|
grantDescrs, err := lg.db.ListGrantsByAccountID(ctx, accountDescr.ID)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
for _, grantDescrs := range grantDescrs {
|
||||||
|
grantShortDescrs := &mbctl.GrantShortDescr{
|
||||||
|
Operation: grantDescrs.Operation,
|
||||||
|
CreatedAt: grantDescrs.CreatedAt,
|
||||||
|
}
|
||||||
|
accountShortDescr.Grants = append(accountShortDescr.Grants, grantShortDescrs)
|
||||||
|
}
|
||||||
|
res.Accounts = append(res.Accounts, accountShortDescr)
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"mbase/app/descriptor"
|
||||||
|
"mbase/pkg/auxid"
|
||||||
|
"mbase/pkg/auxpwd"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultSeedUsername = "certman"
|
||||||
|
defaultSeedPassword = "certman"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (lg *Logic) CleanDatabase(ctx context.Context) error {
|
||||||
|
var err error
|
||||||
|
err = lg.db.CleanDatabase(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lg *Logic) SeedAccount(ctx context.Context) (int64, error) {
|
||||||
|
var err error
|
||||||
|
var accountID int64
|
||||||
|
accountDescrs, err := lg.db.ReducedListAccounts(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return accountID, err
|
||||||
|
}
|
||||||
|
lg.log.Debugf("Seed account")
|
||||||
|
if len(accountDescrs) == 0 {
|
||||||
|
now := time.Now().Format(time.RFC3339)
|
||||||
|
passhash := auxpwd.MakeSHA256Hash([]byte(defaultSeedPassword))
|
||||||
|
accountDescr := &descriptor.Account{
|
||||||
|
ID: auxid.GenID(),
|
||||||
|
Username: defaultSeedUsername,
|
||||||
|
Passhash: passhash,
|
||||||
|
Disabled: false,
|
||||||
|
CreatedAt: now,
|
||||||
|
UpdatedAt: now,
|
||||||
|
}
|
||||||
|
err = lg.db.InsertAccount(ctx, accountDescr)
|
||||||
|
if err != nil {
|
||||||
|
return accountID, err
|
||||||
|
}
|
||||||
|
accountID = accountDescr.ID
|
||||||
|
grantTypes := []string{
|
||||||
|
descriptor.GrantModifyUsers,
|
||||||
|
descriptor.GrantModifyDatabase,
|
||||||
|
}
|
||||||
|
for _, grantType := range grantTypes {
|
||||||
|
grantDescr := &descriptor.Grant{
|
||||||
|
AccountID: accountDescr.ID,
|
||||||
|
Operation: grantType,
|
||||||
|
CreatedAt: now,
|
||||||
|
}
|
||||||
|
err = lg.db.InsertGrant(ctx, grantDescr)
|
||||||
|
if err != nil {
|
||||||
|
return accountID, err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return accountID, err
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"mbase/app/descriptor"
|
||||||
|
"mbase/pkg/mbctl"
|
||||||
|
|
||||||
|
"go.yaml.in/yaml/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (lg *Logic) GetDump(ctx context.Context, accountID int64, params *mbctl.GetDumpParams) (*mbctl.GetDumpResult, error) {
|
||||||
|
var err error
|
||||||
|
res := &mbctl.GetDumpResult{}
|
||||||
|
|
||||||
|
grantExists, _, err := lg.db.GetGrant(ctx, accountID, descriptor.GrantModifyDatabase)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if !grantExists {
|
||||||
|
err := fmt.Errorf("Operation not allowed for the user")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
lg.WaitRestoring()
|
||||||
|
lg.WaitDumping()
|
||||||
|
|
||||||
|
lg.DumpingSemUp()
|
||||||
|
defer lg.DumpingSemDown()
|
||||||
|
|
||||||
|
listAccounts, err := lg.db.CompletedListAccounts(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
listGrants, err := lg.db.ListGrants(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
lg.DumpingSemDown()
|
||||||
|
|
||||||
|
dump := descriptor.Dump{
|
||||||
|
Timestamp: time.Now().Format(time.RFC3339),
|
||||||
|
Accounts: listAccounts,
|
||||||
|
Grants: listGrants,
|
||||||
|
}
|
||||||
|
|
||||||
|
dumpBytes, err := yaml.Marshal(dump)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res.Dump = string(dumpBytes)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lg *Logic) RestoreDump(ctx context.Context, accountID int64, params *mbctl.RestoreDumpParams) (*mbctl.RestoreDumpResult, error) {
|
||||||
|
var err error
|
||||||
|
res := &mbctl.RestoreDumpResult{}
|
||||||
|
|
||||||
|
grantExists, _, err := lg.db.GetGrant(ctx, accountID, descriptor.GrantModifyDatabase)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if !grantExists {
|
||||||
|
err := fmt.Errorf("Operation not allowed for the user")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
lg.WaitDumping()
|
||||||
|
lg.WaitRestoring()
|
||||||
|
|
||||||
|
var dump descriptor.Dump
|
||||||
|
|
||||||
|
err = yaml.Unmarshal([]byte(params.Dump), &dump)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
lg.RestoringSemUp()
|
||||||
|
defer lg.RestoringSemDown()
|
||||||
|
|
||||||
|
if params.DeleteAllRecords {
|
||||||
|
err = lg.db.CleanDatabase(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, account := range dump.Accounts {
|
||||||
|
lg.log.Infof("Insert account %s", account.Username)
|
||||||
|
err = lg.db.InsertAccount(ctx, &account)
|
||||||
|
if err != nil {
|
||||||
|
lg.log.Errorf("Insert account error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, grant := range dump.Grants {
|
||||||
|
lg.log.Infof("Insert grant %s for account %d", grant.Operation, grant.AccountID)
|
||||||
|
err = lg.db.InsertGrant(ctx, &grant)
|
||||||
|
if err != nil {
|
||||||
|
lg.log.Errorf("Insert account error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"mbase/app/descriptor"
|
||||||
|
"mbase/pkg/auxid"
|
||||||
|
"mbase/pkg/mbctl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (lg *Logic) SetGrant(ctx context.Context, accountID int64, params *mbctl.SetGrantParams) (*mbctl.SetGrantResult, error) {
|
||||||
|
var err error
|
||||||
|
res := &mbctl.SetGrantResult{}
|
||||||
|
|
||||||
|
lg.WaitDumping()
|
||||||
|
|
||||||
|
grantExists, _, err := lg.db.GetGrant(ctx, accountID, descriptor.GrantModifyUsers)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if !grantExists {
|
||||||
|
err := fmt.Errorf("Operation not allowed for the user")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
grantTypes := []string{
|
||||||
|
descriptor.GrantModifyUsers,
|
||||||
|
descriptor.GrantModifyDatabase,
|
||||||
|
}
|
||||||
|
var grantOk bool
|
||||||
|
for _, grantType := range grantTypes {
|
||||||
|
if grantType == params.Operation {
|
||||||
|
grantOk = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !grantOk {
|
||||||
|
err := fmt.Errorf("Unknown grant type")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var accountDescr *descriptor.Account
|
||||||
|
var accountExists bool
|
||||||
|
switch {
|
||||||
|
case params.AccountID != 0:
|
||||||
|
accountExists, accountDescr, err = lg.db.GetAccountByID(ctx, params.AccountID)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
case params.Username != "":
|
||||||
|
accountExists, accountDescr, err = lg.db.GetAccountByUsername(ctx, params.Username)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !accountExists || accountDescr == nil {
|
||||||
|
err := fmt.Errorf("Account with this id or name dont exists")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
grantExists, _, err = lg.db.GetGrant(ctx, accountDescr.ID, params.Operation)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if grantExists {
|
||||||
|
err := fmt.Errorf("Grant %s for the user already exists", params.Operation)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
now := time.Now().Format(time.RFC3339)
|
||||||
|
grantDescr := &descriptor.Grant{
|
||||||
|
ID: auxid.GenID(),
|
||||||
|
AccountID: accountDescr.ID,
|
||||||
|
CreatedAt: now,
|
||||||
|
Operation: params.Operation,
|
||||||
|
}
|
||||||
|
err = lg.db.InsertGrant(ctx, grantDescr)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lg *Logic) DeleteGrant(ctx context.Context, accountID int64, params *mbctl.DeleteGrantParams) (*mbctl.DeleteGrantResult, error) {
|
||||||
|
var err error
|
||||||
|
res := &mbctl.DeleteGrantResult{}
|
||||||
|
|
||||||
|
lg.WaitDumping()
|
||||||
|
|
||||||
|
grantExists, _, err := lg.db.GetGrant(ctx, accountID, descriptor.GrantModifyUsers)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if !grantExists {
|
||||||
|
err := fmt.Errorf("Operation not allowed for the user")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
grantTypes := []string{
|
||||||
|
descriptor.GrantModifyUsers,
|
||||||
|
descriptor.GrantModifyDatabase,
|
||||||
|
}
|
||||||
|
var grantOk bool
|
||||||
|
for _, grantType := range grantTypes {
|
||||||
|
if grantType == params.Operation {
|
||||||
|
grantOk = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !grantOk {
|
||||||
|
err := fmt.Errorf("Unknown grant type")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var accountDescr *descriptor.Account
|
||||||
|
var accountExists bool
|
||||||
|
switch {
|
||||||
|
case params.AccountID != 0:
|
||||||
|
accountExists, accountDescr, err = lg.db.GetAccountByID(ctx, params.AccountID)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
case params.Username != "":
|
||||||
|
accountExists, accountDescr, err = lg.db.GetAccountByUsername(ctx, params.Username)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !accountExists || accountDescr == nil {
|
||||||
|
err := fmt.Errorf("Account with this id or name dont exists")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
grantExists, _, err = lg.db.GetGrant(ctx, accountDescr.ID, params.Operation)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if !grantExists {
|
||||||
|
err := fmt.Errorf("Requested grant for the user not found")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
err = lg.db.DeleteGrantByAccountID(ctx, accountDescr.ID, params.Operation)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"mbase/pkg/mbctl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (lg *Logic) GetHello(ctx context.Context, params *mbctl.GetHelloParams) (*mbctl.GetHelloResult, error) {
|
||||||
|
var err error
|
||||||
|
res := &mbctl.GetHelloResult{
|
||||||
|
Message: "hello",
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"mbase/app/database"
|
||||||
|
"mbase/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LogicConfig struct {
|
||||||
|
Database *database.Database
|
||||||
|
}
|
||||||
|
|
||||||
|
type Logic struct {
|
||||||
|
log *logger.Logger
|
||||||
|
db *database.Database
|
||||||
|
dumpingSem atomic.Bool
|
||||||
|
restoringSem atomic.Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLogic(conf *LogicConfig) (*Logic, error) {
|
||||||
|
var err error
|
||||||
|
lg := &Logic{
|
||||||
|
db: conf.Database,
|
||||||
|
}
|
||||||
|
lg.log = logger.NewLogger("logic")
|
||||||
|
return lg, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lg *Logic) DumpingSemUp() {
|
||||||
|
lg.dumpingSem.Store(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lg *Logic) DumpingSemDown() {
|
||||||
|
lg.dumpingSem.Store(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lg *Logic) WaitDumping() {
|
||||||
|
for {
|
||||||
|
if !lg.dumpingSem.Load() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
time.Sleep(1 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lg *Logic) RestoringSemUp() {
|
||||||
|
lg.restoringSem.Store(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lg *Logic) RestoringSemDown() {
|
||||||
|
lg.restoringSem.Store(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lg *Logic) WaitRestoring() {
|
||||||
|
for {
|
||||||
|
if !lg.restoringSem.Load() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
time.Sleep(1 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,360 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"os/user"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"mbase/app/config"
|
||||||
|
"mbase/app/database"
|
||||||
|
"mbase/app/descriptor"
|
||||||
|
"mbase/app/logic"
|
||||||
|
"mbase/pkg/aux509"
|
||||||
|
"mbase/pkg/logger"
|
||||||
|
"mbase/pkg/netacl"
|
||||||
|
|
||||||
|
handler "mbase/app/handler"
|
||||||
|
service "mbase/app/service"
|
||||||
|
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
conf *config.Config
|
||||||
|
lg *logic.Logic
|
||||||
|
svc *service.Service
|
||||||
|
hand *handler.Handler
|
||||||
|
log *logger.Logger
|
||||||
|
nacl *netacl.NetACL
|
||||||
|
|
||||||
|
db *database.Database
|
||||||
|
x509cert []byte
|
||||||
|
x509key []byte
|
||||||
|
state descriptor.Server
|
||||||
|
sfile string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServer() (*Server, error) {
|
||||||
|
var err error
|
||||||
|
srv := &Server{}
|
||||||
|
srv.log = logger.NewLogger("server")
|
||||||
|
return srv, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *Server) Configure() error {
|
||||||
|
var err error
|
||||||
|
srv.conf = config.NewConfig()
|
||||||
|
|
||||||
|
err = srv.conf.ReadFile()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = srv.conf.ReadEnv()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = srv.conf.ReadOpts()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
srv.sfile = filepath.Join(srv.conf.DataDir, "certmanager.yaml")
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *Server) LoadState() error {
|
||||||
|
var err error
|
||||||
|
_, err = os.Stat(srv.sfile)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
err = nil
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
file, err := os.Open(srv.sfile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
stateBytes, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = yaml.Unmarshal(stateBytes, &srv.state)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *Server) SaveState() error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
file, err := os.OpenFile(srv.sfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0640)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
srv.state.UpdatedAt = time.Now().Format(time.RFC3339)
|
||||||
|
if srv.state.CreatedAt == "" {
|
||||||
|
srv.state.CreatedAt = srv.state.UpdatedAt
|
||||||
|
}
|
||||||
|
stateBytes, err := yaml.Marshal(srv.state)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = file.Write(stateBytes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *Server) Build() error {
|
||||||
|
var err error
|
||||||
|
srv.log.Infof("Build server")
|
||||||
|
|
||||||
|
// Mkdir log and data dir
|
||||||
|
srv.log.Infof("Create %s dir", srv.conf.DataDir)
|
||||||
|
err = os.MkdirAll(srv.conf.DataDir, 0750)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if srv.conf.Daemon {
|
||||||
|
logDir := filepath.Dir(srv.conf.LogPath)
|
||||||
|
srv.log.Infof("Create %s dir", logDir)
|
||||||
|
err = os.MkdirAll(logDir, 0750)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
runDir := filepath.Dir(srv.conf.RunPath)
|
||||||
|
srv.log.Infof("Create %s dir", runDir)
|
||||||
|
err = os.MkdirAll(runDir, 0750)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Create X509 certs
|
||||||
|
srv.x509cert, srv.x509key, err = aux509.CreateX509SelfSignedCert(srv.conf.Hostname)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Load state
|
||||||
|
err = srv.LoadState()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Create netACL
|
||||||
|
err = srv.nacl.AddDisabledAddresses(srv.conf.Networks.Disabled...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
srv.nacl = netacl.NewNetACL()
|
||||||
|
err = srv.nacl.AddEnabledAddresses(srv.conf.Networks.Enabled...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
naclYAML, err := yaml.Marshal(srv.nacl)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
srv.log.Infof("Network ACL is:\n%s\n", string(naclYAML))
|
||||||
|
|
||||||
|
// Create database
|
||||||
|
srv.db, err = database.NewDatabase(srv.conf.DataDir)
|
||||||
|
|
||||||
|
err = srv.db.OpenDatabase()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Load state
|
||||||
|
err = srv.LoadState()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Create logic
|
||||||
|
logicConfig := &logic.LogicConfig{
|
||||||
|
Database: srv.db,
|
||||||
|
}
|
||||||
|
srv.lg, err = logic.NewLogic(logicConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !srv.state.DatabaseInitialized {
|
||||||
|
// Create schema
|
||||||
|
srv.log.Infof("Init database")
|
||||||
|
err = srv.db.InitDatabase()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
srv.state.DatabaseInitialized = true
|
||||||
|
err = srv.SaveState()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Create handler
|
||||||
|
handlerConfig := &handler.HandlerConfig{
|
||||||
|
Logic: srv.lg,
|
||||||
|
}
|
||||||
|
srv.hand = handler.NewHandler(handlerConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Create service
|
||||||
|
serviceConfig := &service.ServiceConfig{
|
||||||
|
Portnum: srv.conf.Service.Portnum,
|
||||||
|
Address: srv.conf.Service.Address,
|
||||||
|
Protocol: srv.conf.Service.Protocol,
|
||||||
|
Hostname: srv.conf.Hostname,
|
||||||
|
|
||||||
|
Handler: srv.hand,
|
||||||
|
Logic: srv.lg,
|
||||||
|
X509Cert: srv.x509cert,
|
||||||
|
X509Key: srv.x509key,
|
||||||
|
NetACL: srv.nacl,
|
||||||
|
}
|
||||||
|
srv.svc = service.NewService(serviceConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *Server) Run() error {
|
||||||
|
var err error
|
||||||
|
// Log configuration
|
||||||
|
yamlConfig, err := srv.conf.String()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
srv.log.Debugf("Server configuration:\n%s\n", yamlConfig)
|
||||||
|
|
||||||
|
// Show current user
|
||||||
|
currUser, err := user.Current()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
srv.log.Infof("Running server as user %s", currUser.Username)
|
||||||
|
|
||||||
|
sigs := make(chan os.Signal, 1)
|
||||||
|
done := make(chan error, 1)
|
||||||
|
|
||||||
|
// Run service
|
||||||
|
startService := func(svc *service.Service, done chan error) {
|
||||||
|
err = svc.Run()
|
||||||
|
if err != nil {
|
||||||
|
srv.log.Errorf("Service error: %v", err)
|
||||||
|
done <- err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go startService(srv.svc, done)
|
||||||
|
|
||||||
|
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
var signal os.Signal
|
||||||
|
|
||||||
|
select {
|
||||||
|
case signal = <-sigs:
|
||||||
|
srv.log.Infof("Services stopped by signal: %v", signal)
|
||||||
|
srv.svc.Stop()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *Server) PseudoFork() error {
|
||||||
|
const successExit int = 0
|
||||||
|
var keyEnv string = "IMX0LTSELMRF8KASWER"
|
||||||
|
var err error
|
||||||
|
|
||||||
|
_, isChild := os.LookupEnv(keyEnv)
|
||||||
|
switch {
|
||||||
|
case !isChild:
|
||||||
|
os.Setenv(keyEnv, "TRUE")
|
||||||
|
|
||||||
|
procAttr := syscall.ProcAttr{}
|
||||||
|
cwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var sysFiles = make([]uintptr, 3)
|
||||||
|
sysFiles[0] = uintptr(syscall.Stdin)
|
||||||
|
sysFiles[1] = uintptr(syscall.Stdout)
|
||||||
|
sysFiles[2] = uintptr(syscall.Stderr)
|
||||||
|
|
||||||
|
procAttr.Files = sysFiles
|
||||||
|
procAttr.Env = os.Environ()
|
||||||
|
procAttr.Dir = cwd
|
||||||
|
|
||||||
|
_, err = syscall.ForkExec(os.Args[0], os.Args, &procAttr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
os.Exit(successExit)
|
||||||
|
case isChild:
|
||||||
|
_, err = syscall.Setsid()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os.Unsetenv(keyEnv)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *Server) Daemonize() error {
|
||||||
|
var err error
|
||||||
|
if srv.conf.Daemon {
|
||||||
|
// Restart process process
|
||||||
|
err = srv.PseudoFork()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect stdin
|
||||||
|
nullFile, err := os.OpenFile("/dev/null", os.O_RDWR, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = syscall.Dup2(int(nullFile.Fd()), int(os.Stdin.Fd()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Redirect stderr and stout
|
||||||
|
logdir := filepath.Dir(srv.conf.LogPath)
|
||||||
|
err = os.MkdirAll(logdir, 0750)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logFile, err := os.OpenFile(srv.conf.LogPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = syscall.Dup2(int(logFile.Fd()), int(os.Stdout.Fd()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = syscall.Dup2(int(logFile.Fd()), int(os.Stderr.Fd()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Write process ID
|
||||||
|
rundir := filepath.Dir(srv.conf.RunPath)
|
||||||
|
err = os.MkdirAll(rundir, 0750)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
pidFile, err := os.OpenFile(srv.conf.RunPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0640)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer pidFile.Close()
|
||||||
|
currPid := os.Getpid()
|
||||||
|
_, err = pidFile.WriteString(strconv.Itoa(currPid))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"mbase/app/handler"
|
||||||
|
"mbase/app/logic"
|
||||||
|
"mbase/pkg/logger"
|
||||||
|
"mbase/pkg/netacl"
|
||||||
|
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/credentials"
|
||||||
|
"google.golang.org/grpc/metadata"
|
||||||
|
"google.golang.org/grpc/peer"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ServiceConfig struct {
|
||||||
|
Handler *handler.Handler
|
||||||
|
Logic *logic.Logic
|
||||||
|
NetACL *netacl.NetACL
|
||||||
|
Portnum uint32
|
||||||
|
Address string
|
||||||
|
Protocol string
|
||||||
|
Hostname string
|
||||||
|
X509Cert []byte
|
||||||
|
X509Key []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type Service struct {
|
||||||
|
gsrv *grpc.Server
|
||||||
|
hand *handler.Handler
|
||||||
|
lg *logic.Logic
|
||||||
|
log *logger.Logger
|
||||||
|
nacl *netacl.NetACL
|
||||||
|
portnum uint32
|
||||||
|
address string
|
||||||
|
protocol string
|
||||||
|
hostname string
|
||||||
|
username string
|
||||||
|
password string
|
||||||
|
x509Cert []byte
|
||||||
|
x509Key []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewService(conf *ServiceConfig) *Service {
|
||||||
|
svc := Service{
|
||||||
|
hand: conf.Handler,
|
||||||
|
lg: conf.Logic,
|
||||||
|
nacl: conf.NetACL,
|
||||||
|
portnum: conf.Portnum,
|
||||||
|
address: conf.Address,
|
||||||
|
protocol: conf.Protocol,
|
||||||
|
hostname: conf.Hostname,
|
||||||
|
x509Cert: conf.X509Cert,
|
||||||
|
x509Key: conf.X509Key,
|
||||||
|
}
|
||||||
|
svc.log = logger.NewLogger("gservice")
|
||||||
|
return &svc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (svc *Service) Run() error {
|
||||||
|
var err error
|
||||||
|
svc.log.Infof("Service run")
|
||||||
|
|
||||||
|
listenSpec := fmt.Sprintf("%s:%d", svc.address, svc.portnum)
|
||||||
|
listener, err := net.Listen(svc.protocol, listenSpec)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsCert, err := tls.X509KeyPair(svc.x509Cert, svc.x509Key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tlsConfig := tls.Config{
|
||||||
|
Certificates: []tls.Certificate{tlsCert},
|
||||||
|
ClientAuth: tls.NoClientCert,
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsCredentials := credentials.NewTLS(&tlsConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
interceptors := []grpc.UnaryServerInterceptor{
|
||||||
|
svc.accessInterceptor,
|
||||||
|
svc.logInterceptor,
|
||||||
|
}
|
||||||
|
|
||||||
|
gsrvOpts := []grpc.ServerOption{
|
||||||
|
grpc.Creds(tlsCredentials),
|
||||||
|
grpc.ChainUnaryInterceptor(interceptors...),
|
||||||
|
}
|
||||||
|
svc.gsrv = grpc.NewServer(gsrvOpts...)
|
||||||
|
|
||||||
|
svc.hand.Register(svc.gsrv)
|
||||||
|
|
||||||
|
svc.log.Infof("Service listening at %v", listener.Addr())
|
||||||
|
err = svc.gsrv.Serve(listener)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (svc *Service) accessInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
|
||||||
|
peerMeta, _ := peer.FromContext(ctx)
|
||||||
|
host, _, err := net.SplitHostPort(peerMeta.Addr.String())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
addressEnabled, _ := svc.nacl.AddressIsEnabled(host)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if addressEnabled {
|
||||||
|
svc.log.Warningf("Enable access from %s", host)
|
||||||
|
return handler(ctx, req)
|
||||||
|
}
|
||||||
|
svc.log.Warningf("Disable access from %s", host)
|
||||||
|
return nil, fmt.Errorf("Access disabled by network ACL")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (svc *Service) logInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
|
||||||
|
meta, _ := metadata.FromIncomingContext(ctx)
|
||||||
|
peerMeta, _ := peer.FromContext(ctx)
|
||||||
|
svc.log.Infof("User %v called %v from %s", meta["username"], info.FullMethod, peerMeta.Addr.String())
|
||||||
|
return handler(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (svc *Service) debugInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
|
||||||
|
var err error
|
||||||
|
reqBinary, err := json.Marshal(req)
|
||||||
|
requestString := ""
|
||||||
|
if err == nil {
|
||||||
|
requestString = string(reqBinary)
|
||||||
|
}
|
||||||
|
svc.log.Debugf("Called method: %v with params %v", info.FullMethod, requestString)
|
||||||
|
return handler(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (svc *Service) Stop() {
|
||||||
|
svc.log.Infof("Stopping service")
|
||||||
|
svc.gsrv.GracefulStop()
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"mbase/pkg/mbctl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (util *Util) CreateAccount(ctx context.Context, operID int64) (*mbctl.CreateAccountResult, error) {
|
||||||
|
var err error
|
||||||
|
res := &mbctl.CreateAccountResult{}
|
||||||
|
|
||||||
|
params := &mbctl.CreateAccountParams{
|
||||||
|
Username: util.username,
|
||||||
|
Password: util.password,
|
||||||
|
}
|
||||||
|
res, err = util.lg.CreateAccount(ctx, operID, params)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (util *Util) DeleteAccount(ctx context.Context, operID int64) (*mbctl.DeleteAccountResult, error) {
|
||||||
|
var err error
|
||||||
|
res := &mbctl.DeleteAccountResult{}
|
||||||
|
params := &mbctl.DeleteAccountParams{
|
||||||
|
Username: util.username,
|
||||||
|
AccountID: util.accountID,
|
||||||
|
}
|
||||||
|
res, err = util.lg.DeleteAccount(ctx, operID, params)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (util *Util) ListAccounts(ctx context.Context, operID int64) (*mbctl.ListAccountsResult, error) {
|
||||||
|
var err error
|
||||||
|
res := &mbctl.ListAccountsResult{}
|
||||||
|
params := &mbctl.ListAccountsParams{}
|
||||||
|
res, err = util.lg.ListAccounts(ctx, operID, params)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (util *Util) UpdateAccount(ctx context.Context, operID int64) (*mbctl.UpdateAccountResult, error) {
|
||||||
|
var err error
|
||||||
|
res := &mbctl.UpdateAccountResult{}
|
||||||
|
params := &mbctl.UpdateAccountParams{
|
||||||
|
Username: util.username,
|
||||||
|
AccountID: util.accountID,
|
||||||
|
NewUsername: util.newUsername,
|
||||||
|
NewPassword: util.newPassword,
|
||||||
|
}
|
||||||
|
res, err = util.lg.UpdateAccount(ctx, operID, params)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"mbase/pkg/mbctl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (util *Util) SetGrant(ctx context.Context, operID int64) (*mbctl.SetGrantResult, error) {
|
||||||
|
var err error
|
||||||
|
res := &mbctl.SetGrantResult{}
|
||||||
|
params := &mbctl.SetGrantParams{
|
||||||
|
Username: util.username,
|
||||||
|
AccountID: util.accountID,
|
||||||
|
Operation: util.operation,
|
||||||
|
}
|
||||||
|
res, err = util.lg.SetGrant(ctx, operID, params)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (util *Util) DeleteGrant(ctx context.Context, operID int64) (*mbctl.DeleteGrantResult, error) {
|
||||||
|
var err error
|
||||||
|
res := &mbctl.DeleteGrantResult{}
|
||||||
|
params := &mbctl.DeleteGrantParams{
|
||||||
|
Username: util.username,
|
||||||
|
AccountID: util.accountID,
|
||||||
|
Operation: util.operation,
|
||||||
|
}
|
||||||
|
res, err = util.lg.DeleteGrant(ctx, operID, params)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,467 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Oleg Borodin <borodin@unix7.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"mbase/app/config"
|
||||||
|
"mbase/app/database"
|
||||||
|
"mbase/app/descriptor"
|
||||||
|
"mbase/app/logic"
|
||||||
|
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
rcFilename = ".certmanager.yaml"
|
||||||
|
|
||||||
|
helpCmd = "help"
|
||||||
|
|
||||||
|
createAccountCmd = "createAccount"
|
||||||
|
updateAccountCmd = "updateAccount"
|
||||||
|
deleteAccountCmd = "deleteAccount"
|
||||||
|
listAccountsCmd = "listAccounts"
|
||||||
|
|
||||||
|
setGrantCmd = "setGrant"
|
||||||
|
deleteGrantCmd = "deleteGrant"
|
||||||
|
|
||||||
|
initDatabaseCmd = "initDatabase"
|
||||||
|
seedAccountCmd = "seedAccount"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var err error
|
||||||
|
util := NewUtil()
|
||||||
|
err = util.Build()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Build error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
err = util.Exec()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Exec error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Util struct {
|
||||||
|
subCmd string
|
||||||
|
cmdTimeout int64
|
||||||
|
|
||||||
|
conf *config.Config
|
||||||
|
lg *logic.Logic
|
||||||
|
db *database.Database
|
||||||
|
state descriptor.Server
|
||||||
|
sfile string
|
||||||
|
|
||||||
|
accessUsername string
|
||||||
|
accessPassword string
|
||||||
|
accountID int64
|
||||||
|
username string
|
||||||
|
password string
|
||||||
|
disable bool
|
||||||
|
newUsername string
|
||||||
|
newPassword string
|
||||||
|
operation string
|
||||||
|
quiet bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUtil() *Util {
|
||||||
|
var util Util
|
||||||
|
util.cmdTimeout = 120
|
||||||
|
return &util
|
||||||
|
}
|
||||||
|
|
||||||
|
func (util *Util) GetOpt() error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
exeName := filepath.Base(os.Args[0])
|
||||||
|
|
||||||
|
flag.Int64Var(&util.cmdTimeout, "timeout", util.cmdTimeout, "command execution timeout")
|
||||||
|
flag.StringVar(&util.accessUsername, "user", util.accessUsername, "access login")
|
||||||
|
flag.StringVar(&util.accessPassword, "pass", util.accessPassword, "access password")
|
||||||
|
flag.BoolVar(&util.quiet, "quiet", util.quiet, "don't print result")
|
||||||
|
|
||||||
|
help := func() {
|
||||||
|
fmt.Println("")
|
||||||
|
fmt.Printf("Usage: %s [option] command [command option]\n", exeName)
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf(" %s, %s, %s, %s,\n",
|
||||||
|
createAccountCmd,
|
||||||
|
deleteAccountCmd,
|
||||||
|
listAccountsCmd,
|
||||||
|
updateAccountCmd)
|
||||||
|
fmt.Printf(" %s, %s\n",
|
||||||
|
setGrantCmd,
|
||||||
|
deleteGrantCmd)
|
||||||
|
fmt.Printf(" %s, %s\n",
|
||||||
|
initDatabaseCmd,
|
||||||
|
seedAccountCmd)
|
||||||
|
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("Global options:\n")
|
||||||
|
flag.PrintDefaults()
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
flag.Usage = help
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
args := flag.Args()
|
||||||
|
|
||||||
|
var subCmd string
|
||||||
|
var subArgs []string
|
||||||
|
if len(args) > 0 {
|
||||||
|
subCmd = args[0]
|
||||||
|
subArgs = args[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
util.subCmd = subCmd
|
||||||
|
|
||||||
|
switch subCmd {
|
||||||
|
case helpCmd:
|
||||||
|
help()
|
||||||
|
return errors.New("Unknown command")
|
||||||
|
|
||||||
|
case createAccountCmd:
|
||||||
|
flagSet := flag.NewFlagSet(createAccountCmd, flag.ExitOnError)
|
||||||
|
|
||||||
|
flagSet.StringVar(&util.username, "username", util.username, "user name")
|
||||||
|
flagSet.StringVar(&util.password, "password", util.password, "user password")
|
||||||
|
|
||||||
|
flagSet.Usage = func() {
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("Usage: %s [global options] %s [command options]\n", exeName, subCmd)
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("The command options: none\n")
|
||||||
|
flagSet.PrintDefaults()
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
flagSet.Parse(subArgs)
|
||||||
|
util.subCmd = subCmd
|
||||||
|
|
||||||
|
case deleteAccountCmd:
|
||||||
|
flagSet := flag.NewFlagSet(deleteAccountCmd, flag.ExitOnError)
|
||||||
|
|
||||||
|
flagSet.StringVar(&util.username, "username", util.username, "user name")
|
||||||
|
flagSet.Int64Var(&util.accountID, "accountId", util.accountID, "account ID")
|
||||||
|
|
||||||
|
flagSet.Usage = func() {
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("Usage: %s [global options] %s [command options]\n", exeName, subCmd)
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("The command options: none\n")
|
||||||
|
flagSet.PrintDefaults()
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
flagSet.Parse(subArgs)
|
||||||
|
util.subCmd = subCmd
|
||||||
|
|
||||||
|
case listAccountsCmd:
|
||||||
|
flagSet := flag.NewFlagSet(listAccountsCmd, flag.ExitOnError)
|
||||||
|
|
||||||
|
flagSet.Usage = func() {
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("Usage: %s [global options] %s [command options]\n", exeName, subCmd)
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("The command options: none\n")
|
||||||
|
flagSet.PrintDefaults()
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
flagSet.Parse(subArgs)
|
||||||
|
util.subCmd = subCmd
|
||||||
|
|
||||||
|
case updateAccountCmd:
|
||||||
|
flagSet := flag.NewFlagSet(updateAccountCmd, flag.ExitOnError)
|
||||||
|
|
||||||
|
flagSet.StringVar(&util.username, "username", util.username, "user name")
|
||||||
|
flagSet.Int64Var(&util.accountID, "accountId", util.accountID, "account ID")
|
||||||
|
|
||||||
|
flagSet.StringVar(&util.newUsername, "newUsername", util.newUsername, "new user name")
|
||||||
|
flagSet.StringVar(&util.newPassword, "newPassword", util.newPassword, "new user password")
|
||||||
|
flagSet.BoolVar(&util.disable, "disable", util.disable, "disable account")
|
||||||
|
|
||||||
|
flagSet.Usage = func() {
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("Usage: %s [global options] %s [command options]\n", exeName, subCmd)
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("The command options: none\n")
|
||||||
|
flagSet.PrintDefaults()
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
flagSet.Parse(subArgs)
|
||||||
|
util.subCmd = subCmd
|
||||||
|
|
||||||
|
case setGrantCmd:
|
||||||
|
flagSet := flag.NewFlagSet(setGrantCmd, flag.ExitOnError)
|
||||||
|
|
||||||
|
flagSet.StringVar(&util.username, "username", util.username, "user name")
|
||||||
|
flagSet.Int64Var(&util.accountID, "accountId", util.accountID, "account ID")
|
||||||
|
flagSet.StringVar(&util.operation, "operation", util.operation, "grant type")
|
||||||
|
|
||||||
|
flagSet.Usage = func() {
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("Usage: %s [global options] %s [command options]\n", exeName, subCmd)
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("The command options: none\n")
|
||||||
|
flagSet.PrintDefaults()
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
flagSet.Parse(subArgs)
|
||||||
|
util.subCmd = subCmd
|
||||||
|
|
||||||
|
case deleteGrantCmd:
|
||||||
|
flagSet := flag.NewFlagSet(deleteGrantCmd, flag.ExitOnError)
|
||||||
|
|
||||||
|
flagSet.StringVar(&util.username, "username", util.username, "user name")
|
||||||
|
flagSet.Int64Var(&util.accountID, "accountId", util.accountID, "account ID")
|
||||||
|
flagSet.StringVar(&util.operation, "operation", util.operation, "grant type")
|
||||||
|
|
||||||
|
flagSet.Usage = func() {
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("Usage: %s [global options] %s [command options]\n", exeName, subCmd)
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("The command options: none\n")
|
||||||
|
flagSet.PrintDefaults()
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
flagSet.Parse(subArgs)
|
||||||
|
util.subCmd = subCmd
|
||||||
|
|
||||||
|
case initDatabaseCmd:
|
||||||
|
flagSet := flag.NewFlagSet(initDatabaseCmd, flag.ExitOnError)
|
||||||
|
|
||||||
|
flagSet.Usage = func() {
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("Usage: %s [global options] %s [command options]\n", exeName, subCmd)
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("The command options: none\n")
|
||||||
|
flagSet.PrintDefaults()
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
flagSet.Parse(subArgs)
|
||||||
|
util.subCmd = subCmd
|
||||||
|
case seedAccountCmd:
|
||||||
|
flagSet := flag.NewFlagSet(seedAccountCmd, flag.ExitOnError)
|
||||||
|
|
||||||
|
flagSet.Usage = func() {
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("Usage: %s [global options] %s [command options]\n", exeName, subCmd)
|
||||||
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("The command options: none\n")
|
||||||
|
flagSet.PrintDefaults()
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
flagSet.Parse(subArgs)
|
||||||
|
util.subCmd = subCmd
|
||||||
|
|
||||||
|
default:
|
||||||
|
help()
|
||||||
|
return errors.New("Unknown command")
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (util *Util) Build() error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
util.conf = config.NewConfig()
|
||||||
|
err = util.conf.ReadFile()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = util.conf.ReadEnv()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
util.sfile = filepath.Join(util.conf.DataDir, "certmanager.yaml")
|
||||||
|
|
||||||
|
db, err := database.NewDatabase(util.conf.DataDir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = db.OpenDatabase()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
util.db = db
|
||||||
|
logicConfig := &logic.LogicConfig{
|
||||||
|
Database: util.db,
|
||||||
|
}
|
||||||
|
util.lg, err = logic.NewLogic(logicConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type Response struct {
|
||||||
|
Command string `json:"command" yaml:"command"`
|
||||||
|
Args []string `json:"args" yaml:"args"`
|
||||||
|
Error bool `json:"error" yaml:"error"`
|
||||||
|
Message string `json:"message,omitempty" yaml:"message,omitempty"`
|
||||||
|
Result any `json:"result,omitempty" yaml:"result,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (util *Util) Exec() error {
|
||||||
|
var err error
|
||||||
|
err = util.GetOpt()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var timeout = time.Duration(util.cmdTimeout) * time.Second
|
||||||
|
ctx, close := context.WithTimeout(context.Background(), timeout)
|
||||||
|
defer close()
|
||||||
|
|
||||||
|
var res any
|
||||||
|
|
||||||
|
switch util.subCmd {
|
||||||
|
case initDatabaseCmd:
|
||||||
|
res, err = util.InitDatabase(ctx)
|
||||||
|
case seedAccountCmd:
|
||||||
|
res, err = util.SeedAccount(ctx)
|
||||||
|
default:
|
||||||
|
authOk, operID, localErr := util.lg.ValidateAcount(ctx, util.accessUsername, util.accessPassword)
|
||||||
|
if err != nil {
|
||||||
|
err = localErr
|
||||||
|
goto exit
|
||||||
|
}
|
||||||
|
if !authOk {
|
||||||
|
err = fmt.Errorf("Incorrect username or password")
|
||||||
|
goto exit
|
||||||
|
}
|
||||||
|
switch util.subCmd {
|
||||||
|
case createAccountCmd:
|
||||||
|
res, err = util.CreateAccount(ctx, operID)
|
||||||
|
case updateAccountCmd:
|
||||||
|
res, err = util.UpdateAccount(ctx, operID)
|
||||||
|
case listAccountsCmd:
|
||||||
|
res, err = util.ListAccounts(ctx, operID)
|
||||||
|
case deleteAccountCmd:
|
||||||
|
res, err = util.DeleteAccount(ctx, operID)
|
||||||
|
case setGrantCmd:
|
||||||
|
res, err = util.SetGrant(ctx, operID)
|
||||||
|
case deleteGrantCmd:
|
||||||
|
res, err = util.DeleteGrant(ctx, operID)
|
||||||
|
default:
|
||||||
|
err = errors.New("Unknown cli command")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
var resp Response
|
||||||
|
resp.Command = util.subCmd
|
||||||
|
resp.Args = os.Args
|
||||||
|
if err != nil {
|
||||||
|
resp.Error = true
|
||||||
|
resp.Message = fmt.Sprintf("%v", err)
|
||||||
|
} else {
|
||||||
|
resp.Result = res
|
||||||
|
}
|
||||||
|
|
||||||
|
if !resp.Error && !util.quiet {
|
||||||
|
respBytes, _ := yaml.Marshal(resp)
|
||||||
|
fmt.Println(string(respBytes))
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type InitDatabaseRes struct{}
|
||||||
|
|
||||||
|
func (util *Util) InitDatabase(ctx context.Context) (InitDatabaseRes, error) {
|
||||||
|
res := InitDatabaseRes{}
|
||||||
|
// Initialize database
|
||||||
|
|
||||||
|
// Load state
|
||||||
|
err := util.LoadState()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if !util.state.DatabaseInitialized {
|
||||||
|
if util.db == nil {
|
||||||
|
err = fmt.Errorf("Nil db object")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
err := util.db.InitDatabase()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
util.state.DatabaseInitialized = true
|
||||||
|
err = util.SaveState()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type SeedAccountRes struct{}
|
||||||
|
|
||||||
|
func (util *Util) SeedAccount(ctx context.Context) (SeedAccountRes, error) {
|
||||||
|
// Seed accounts
|
||||||
|
res := SeedAccountRes{}
|
||||||
|
_, err := util.lg.SeedAccount(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (util *Util) LoadState() error {
|
||||||
|
var err error
|
||||||
|
_, err = os.Stat(util.sfile)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
err = nil
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
file, err := os.Open(util.sfile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
stateBytes, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = yaml.Unmarshal(stateBytes, &util.state)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (util *Util) SaveState() error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
file, err := os.OpenFile(util.sfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0640)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
util.state.UpdatedAt = time.Now().Format(time.RFC3339)
|
||||||
|
if util.state.CreatedAt == "" {
|
||||||
|
util.state.CreatedAt = util.state.UpdatedAt
|
||||||
|
}
|
||||||
|
stateBytes, err := yaml.Marshal(util.state)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = file.Write(stateBytes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||||
|
*/
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var err error
|
||||||
|
util := NewUtil()
|
||||||
|
err = util.Build()
|
||||||
|
if err != nil {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
err = util.Exec(os.Args[1:])
|
||||||
|
if err != nil {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||||
|
*/
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
func printResponse(res any, err error) {
|
||||||
|
type Response struct {
|
||||||
|
Error bool `json:"error" yaml:"error"`
|
||||||
|
Message string `json:"message,omitempty" yaml:"message,omitempty"`
|
||||||
|
Result any `json:"result,omitempty" yaml:"result,omitempty"`
|
||||||
|
}
|
||||||
|
resp := Response{}
|
||||||
|
if err != nil {
|
||||||
|
resp.Error = true
|
||||||
|
resp.Message = err.Error()
|
||||||
|
} else {
|
||||||
|
resp.Result = res
|
||||||
|
}
|
||||||
|
respBytes, _ := yaml.Marshal(resp)
|
||||||
|
fmt.Printf("---\n%s\n", string(respBytes))
|
||||||
|
}
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||||
|
*/
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"bytes"
|
||||||
|
|
||||||
|
"mbase/app/config"
|
||||||
|
"mbase/app/database"
|
||||||
|
"mbase/app/descriptor"
|
||||||
|
"mbase/pkg/auxtool"
|
||||||
|
"mbase/pkg/logger"
|
||||||
|
|
||||||
|
"go.yaml.in/yaml/v4"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Util struct {
|
||||||
|
rootCmd *cobra.Command
|
||||||
|
dumpDatabaseParams dumpDatabaseParams
|
||||||
|
restoreDatabaseParams restoreDatabaseParams
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUtil() *Util {
|
||||||
|
return &Util{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (util *Util) GetRooCmd() *cobra.Command {
|
||||||
|
return util.rootCmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (util *Util) Build() error {
|
||||||
|
var err error
|
||||||
|
execName := filepath.Base(os.Args[0])
|
||||||
|
rootCmd := &cobra.Command{
|
||||||
|
Use: execName,
|
||||||
|
Short: "\nDump application database",
|
||||||
|
SilenceUsage: true,
|
||||||
|
}
|
||||||
|
rootCmd.CompletionOptions.DisableDefaultCmd = true
|
||||||
|
|
||||||
|
var dumpDatabaseCmd = &cobra.Command{
|
||||||
|
Use: "dump [filename|-]",
|
||||||
|
Short: "Dump application database",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: util.DumpDatabase,
|
||||||
|
}
|
||||||
|
rootCmd.AddCommand(dumpDatabaseCmd)
|
||||||
|
|
||||||
|
var restoreDatabaseCmd = &cobra.Command{
|
||||||
|
Use: "restore [] [filename|-]",
|
||||||
|
Short: "Restore application database",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: util.RestoreDatabase,
|
||||||
|
}
|
||||||
|
restoreDatabaseCmd.Flags().BoolVarP(&util.restoreDatabaseParams.DeleteAllRecords, "clean", "C", false, "Clean all record")
|
||||||
|
rootCmd.AddCommand(restoreDatabaseCmd)
|
||||||
|
|
||||||
|
util.rootCmd = rootCmd
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (util *Util) Exec(args []string) error {
|
||||||
|
var err error
|
||||||
|
util.rootCmd.SetArgs(args)
|
||||||
|
err = util.rootCmd.Execute()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (util *Util) DumpDatabase(cmd *cobra.Command, args []string) {
|
||||||
|
util.dumpDatabaseParams.Filename = args[0]
|
||||||
|
res, err := util.dumpDatabase(util.dumpDatabaseParams)
|
||||||
|
printResponse(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type dumpDatabaseParams struct {
|
||||||
|
Filename string
|
||||||
|
}
|
||||||
|
type dumpDatabaseResult struct {}
|
||||||
|
|
||||||
|
func (util *Util) dumpDatabase(params dumpDatabaseParams) (dumpDatabaseResult, error) {
|
||||||
|
var err error
|
||||||
|
res := dumpDatabaseResult{}
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
conf := config.NewConfig()
|
||||||
|
err = conf.ReadFile()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
err = conf.ReadEnv()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
db, err := database.NewDatabase(conf.DataDir)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
err = db.OpenDatabase()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
file := os.Stdout
|
||||||
|
if params.Filename != "-" {
|
||||||
|
file, err = os.OpenFile(params.Filename, os.O_CREATE|os.O_WRONLY, 0640)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
}
|
||||||
|
listAccounts, err := db.CompletedListAccounts(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
listGrants, err := db.ListGrants(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
dump := descriptor.Dump{
|
||||||
|
Timestamp: auxtool.TimeNow(),
|
||||||
|
Accounts: listAccounts,
|
||||||
|
Grants: listGrants,
|
||||||
|
}
|
||||||
|
dumpBytes, err := yaml.Marshal(dump)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
_, err = file.Write(dumpBytes)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (util *Util) RestoreDatabase(cmd *cobra.Command, args []string) {
|
||||||
|
util.restoreDatabaseParams.Filename = args[0]
|
||||||
|
res, err := util.restoreDatabase(util.restoreDatabaseParams)
|
||||||
|
printResponse(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type restoreDatabaseParams struct {
|
||||||
|
Filename string
|
||||||
|
DeleteAllRecords bool
|
||||||
|
}
|
||||||
|
type restoreDatabaseResult struct {}
|
||||||
|
|
||||||
|
func (util *Util) restoreDatabase(params restoreDatabaseParams) (restoreDatabaseResult, error) {
|
||||||
|
var err error
|
||||||
|
res := restoreDatabaseResult{}
|
||||||
|
ctx := context.Background()
|
||||||
|
log := logger.NewLogger("restore")
|
||||||
|
|
||||||
|
conf := config.NewConfig()
|
||||||
|
err = conf.ReadFile()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
err = conf.ReadEnv()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := database.NewDatabase(conf.DataDir)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
err = db.OpenDatabase()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
file := os.Stdin
|
||||||
|
if params.Filename != "-" {
|
||||||
|
file, err = os.Open(params.Filename)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
}
|
||||||
|
buffer := bytes.NewBuffer(nil)
|
||||||
|
_, err = io.Copy(buffer, file)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
dump := descriptor.Dump{}
|
||||||
|
err = yaml.Unmarshal(buffer.Bytes(), &dump)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if params.DeleteAllRecords {
|
||||||
|
err = db.CleanDatabase(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, account := range dump.Accounts {
|
||||||
|
log.Infof("Insert account %s", account.Username)
|
||||||
|
err = db.InsertAccount(ctx, &account)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Insert account error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, grant := range dump.Grants {
|
||||||
|
log.Infof("Insert grant %s for account %d", grant.Operation, grant.AccountID)
|
||||||
|
err = db.InsertGrant(ctx, &grant)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Insert account error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 Oleg Borodin <borodin@unix7.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"mbase/app/config"
|
||||||
|
"mbase/app/database"
|
||||||
|
"mbase/app/descriptor"
|
||||||
|
"mbase/pkg/logger"
|
||||||
|
|
||||||
|
"go.yaml.in/yaml/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var err error
|
||||||
|
util := NewUtil()
|
||||||
|
err = util.Exec()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Exec error: %s\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Util struct {
|
||||||
|
conf *config.Config
|
||||||
|
db *database.Database
|
||||||
|
log *logger.Logger
|
||||||
|
|
||||||
|
filename string
|
||||||
|
deleteAllRecords bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUtil() *Util {
|
||||||
|
var util Util
|
||||||
|
util.log = logger.NewLogger("logic")
|
||||||
|
return &util
|
||||||
|
}
|
||||||
|
|
||||||
|
func (util *Util) GetOpt() error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
exeName := filepath.Base(os.Args[0])
|
||||||
|
|
||||||
|
help := func() {
|
||||||
|
fmt.Println("")
|
||||||
|
fmt.Printf("Usage: %s [option]\n", exeName)
|
||||||
|
fmt.Printf("\n")
|
||||||
|
flag.PrintDefaults()
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
flag.Usage = help
|
||||||
|
|
||||||
|
flag.StringVar(&util.filename, "file", util.filename, "dump file name")
|
||||||
|
flag.BoolVar(&util.deleteAllRecords, "deleteAllRecords", util.deleteAllRecords, "delete all existing records before restoring")
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (util *Util) Exec() error {
|
||||||
|
var err error
|
||||||
|
err = util.GetOpt()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeout = 30 * time.Second
|
||||||
|
ctx, _ := context.WithTimeout(context.Background(), timeout)
|
||||||
|
|
||||||
|
err = util.RestoreRecords(ctx)
|
||||||
|
|
||||||
|
type ErrorDescr struct {
|
||||||
|
Error bool `json:"error,omitempty"`
|
||||||
|
Message string `json:"errorMessage,omitempty" yaml:"errorMessage,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
errDescr := ErrorDescr{}
|
||||||
|
if err != nil {
|
||||||
|
errDescr.Error = true
|
||||||
|
errDescr.Message = fmt.Sprintf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
errBytes, _ := yaml.Marshal(errDescr)
|
||||||
|
fmt.Printf("%s\n", string(errBytes))
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (util *Util) RestoreRecords(ctx context.Context) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
util.conf = config.NewConfig()
|
||||||
|
err = util.conf.ReadFile()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = util.conf.ReadEnv()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := database.NewDatabase(util.conf.DataDir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
util.db = db
|
||||||
|
|
||||||
|
err = util.db.OpenDatabase()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
file := os.Stdin
|
||||||
|
if util.filename != "" {
|
||||||
|
file, err = os.Open(util.filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := bytes.NewBuffer(nil)
|
||||||
|
_, err = io.Copy(buffer, file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
dump := descriptor.Dump{}
|
||||||
|
|
||||||
|
err = yaml.Unmarshal(buffer.Bytes(), &dump)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if util.deleteAllRecords {
|
||||||
|
err = util.db.CleanDatabase(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, account := range dump.Accounts {
|
||||||
|
util.log.Infof("Insert account %s", account.Username)
|
||||||
|
err = util.db.InsertAccount(ctx, &account)
|
||||||
|
if err != nil {
|
||||||
|
util.log.Errorf("Insert account error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, grant := range dump.Grants {
|
||||||
|
util.log.Infof("Insert grant %s for account %d", grant.Operation, grant.AccountID)
|
||||||
|
err = util.db.InsertGrant(ctx, &grant)
|
||||||
|
if err != nil {
|
||||||
|
util.log.Errorf("Insert account error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1,351 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
# Wrapper for compilers which do not understand '-c -o'.
|
||||||
|
|
||||||
|
scriptversion=2024-06-19.01; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 1999-2024 Free Software Foundation, Inc.
|
||||||
|
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# As a special exception to the GNU General Public License, if you
|
||||||
|
# distribute this file as part of a program that contains a
|
||||||
|
# configuration script generated by Autoconf, you may include it under
|
||||||
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
# This file is maintained in Automake, please report
|
||||||
|
# bugs to <bug-automake@gnu.org> or send patches to
|
||||||
|
# <automake-patches@gnu.org>.
|
||||||
|
|
||||||
|
nl='
|
||||||
|
'
|
||||||
|
|
||||||
|
# We need space, tab and new line, in precisely that order. Quoting is
|
||||||
|
# there to prevent tools from complaining about whitespace usage.
|
||||||
|
IFS=" "" $nl"
|
||||||
|
|
||||||
|
file_conv=
|
||||||
|
|
||||||
|
# func_file_conv build_file lazy
|
||||||
|
# Convert a $build file to $host form and store it in $file
|
||||||
|
# Currently only supports Windows hosts. If the determined conversion
|
||||||
|
# type is listed in (the comma separated) LAZY, no conversion will
|
||||||
|
# take place.
|
||||||
|
func_file_conv ()
|
||||||
|
{
|
||||||
|
file=$1
|
||||||
|
case $file in
|
||||||
|
/ | /[!/]*) # absolute file, and not a UNC file
|
||||||
|
if test -z "$file_conv"; then
|
||||||
|
# lazily determine how to convert abs files
|
||||||
|
case `uname -s` in
|
||||||
|
MINGW*)
|
||||||
|
file_conv=mingw
|
||||||
|
;;
|
||||||
|
CYGWIN* | MSYS*)
|
||||||
|
file_conv=cygwin
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
file_conv=wine
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
case $file_conv/,$2, in
|
||||||
|
*,$file_conv,*)
|
||||||
|
;;
|
||||||
|
mingw/*)
|
||||||
|
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||||
|
;;
|
||||||
|
cygwin/* | msys/*)
|
||||||
|
file=`cygpath -m "$file" || echo "$file"`
|
||||||
|
;;
|
||||||
|
wine/*)
|
||||||
|
file=`winepath -w "$file" || echo "$file"`
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# func_cl_dashL linkdir
|
||||||
|
# Make cl look for libraries in LINKDIR
|
||||||
|
func_cl_dashL ()
|
||||||
|
{
|
||||||
|
func_file_conv "$1"
|
||||||
|
if test -z "$lib_path"; then
|
||||||
|
lib_path=$file
|
||||||
|
else
|
||||||
|
lib_path="$lib_path;$file"
|
||||||
|
fi
|
||||||
|
linker_opts="$linker_opts -LIBPATH:$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# func_cl_dashl library
|
||||||
|
# Do a library search-path lookup for cl
|
||||||
|
func_cl_dashl ()
|
||||||
|
{
|
||||||
|
lib=$1
|
||||||
|
found=no
|
||||||
|
save_IFS=$IFS
|
||||||
|
IFS=';'
|
||||||
|
for dir in $lib_path $LIB
|
||||||
|
do
|
||||||
|
IFS=$save_IFS
|
||||||
|
if $shared && test -f "$dir/$lib.dll.lib"; then
|
||||||
|
found=yes
|
||||||
|
lib=$dir/$lib.dll.lib
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if test -f "$dir/$lib.lib"; then
|
||||||
|
found=yes
|
||||||
|
lib=$dir/$lib.lib
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if test -f "$dir/lib$lib.a"; then
|
||||||
|
found=yes
|
||||||
|
lib=$dir/lib$lib.a
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS=$save_IFS
|
||||||
|
|
||||||
|
if test "$found" != yes; then
|
||||||
|
lib=$lib.lib
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# func_cl_wrapper cl arg...
|
||||||
|
# Adjust compile command to suit cl
|
||||||
|
func_cl_wrapper ()
|
||||||
|
{
|
||||||
|
# Assume a capable shell
|
||||||
|
lib_path=
|
||||||
|
shared=:
|
||||||
|
linker_opts=
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
if test -n "$eat"; then
|
||||||
|
eat=
|
||||||
|
else
|
||||||
|
case $1 in
|
||||||
|
-o)
|
||||||
|
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||||
|
eat=1
|
||||||
|
case $2 in
|
||||||
|
*.o | *.lo | *.[oO][bB][jJ])
|
||||||
|
func_file_conv "$2"
|
||||||
|
set x "$@" -Fo"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
func_file_conv "$2"
|
||||||
|
set x "$@" -Fe"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
-I)
|
||||||
|
eat=1
|
||||||
|
func_file_conv "$2" mingw
|
||||||
|
set x "$@" -I"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-I*)
|
||||||
|
func_file_conv "${1#-I}" mingw
|
||||||
|
set x "$@" -I"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-l)
|
||||||
|
eat=1
|
||||||
|
func_cl_dashl "$2"
|
||||||
|
set x "$@" "$lib"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-l*)
|
||||||
|
func_cl_dashl "${1#-l}"
|
||||||
|
set x "$@" "$lib"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-L)
|
||||||
|
eat=1
|
||||||
|
func_cl_dashL "$2"
|
||||||
|
;;
|
||||||
|
-L*)
|
||||||
|
func_cl_dashL "${1#-L}"
|
||||||
|
;;
|
||||||
|
-static)
|
||||||
|
shared=false
|
||||||
|
;;
|
||||||
|
-Wl,*)
|
||||||
|
arg=${1#-Wl,}
|
||||||
|
save_ifs="$IFS"; IFS=','
|
||||||
|
for flag in $arg; do
|
||||||
|
IFS="$save_ifs"
|
||||||
|
linker_opts="$linker_opts $flag"
|
||||||
|
done
|
||||||
|
IFS="$save_ifs"
|
||||||
|
;;
|
||||||
|
-Xlinker)
|
||||||
|
eat=1
|
||||||
|
linker_opts="$linker_opts $2"
|
||||||
|
;;
|
||||||
|
-*)
|
||||||
|
set x "$@" "$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
|
||||||
|
func_file_conv "$1"
|
||||||
|
set x "$@" -Tp"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
|
||||||
|
func_file_conv "$1" mingw
|
||||||
|
set x "$@" "$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set x "$@" "$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
if test -n "$linker_opts"; then
|
||||||
|
linker_opts="-link$linker_opts"
|
||||||
|
fi
|
||||||
|
exec "$@" $linker_opts
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
eat=
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
'')
|
||||||
|
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||||
|
exit 1;
|
||||||
|
;;
|
||||||
|
-h | --h*)
|
||||||
|
cat <<\EOF
|
||||||
|
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||||
|
|
||||||
|
Wrapper for compilers which do not understand '-c -o'.
|
||||||
|
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||||
|
arguments, and rename the output as expected.
|
||||||
|
|
||||||
|
If you are trying to build a whole package this is not the
|
||||||
|
right script to run: please start by reading the file 'INSTALL'.
|
||||||
|
|
||||||
|
Report bugs to <bug-automake@gnu.org>.
|
||||||
|
GNU Automake home page: <https://www.gnu.org/software/automake/>.
|
||||||
|
General help using GNU software: <https://www.gnu.org/gethelp/>.
|
||||||
|
EOF
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
-v | --v*)
|
||||||
|
echo "compile (GNU Automake) $scriptversion"
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
|
||||||
|
clang-cl | *[/\\]clang-cl | clang-cl.exe | *[/\\]clang-cl.exe | \
|
||||||
|
icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
|
||||||
|
func_cl_wrapper "$@" # Doesn't return...
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
ofile=
|
||||||
|
cfile=
|
||||||
|
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
if test -n "$eat"; then
|
||||||
|
eat=
|
||||||
|
else
|
||||||
|
case $1 in
|
||||||
|
-o)
|
||||||
|
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||||
|
# So we strip '-o arg' only if arg is an object.
|
||||||
|
eat=1
|
||||||
|
case $2 in
|
||||||
|
*.o | *.obj)
|
||||||
|
ofile=$2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set x "$@" -o "$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*.c)
|
||||||
|
cfile=$1
|
||||||
|
set x "$@" "$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set x "$@" "$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if test -z "$ofile" || test -z "$cfile"; then
|
||||||
|
# If no '-o' option was seen then we might have been invoked from a
|
||||||
|
# pattern rule where we don't need one. That is ok -- this is a
|
||||||
|
# normal compilation that the losing compiler can handle. If no
|
||||||
|
# '.c' file was seen then we are probably linking. That is also
|
||||||
|
# ok.
|
||||||
|
exec "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Name of file we expect compiler to create.
|
||||||
|
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||||
|
|
||||||
|
# Create the lock directory.
|
||||||
|
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
|
||||||
|
# that we are using for the .o file. Also, base the name on the expected
|
||||||
|
# object file name, since that is what matters with a parallel build.
|
||||||
|
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||||
|
while true; do
|
||||||
|
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
# FIXME: race condition here if user kills between mkdir and trap.
|
||||||
|
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||||
|
|
||||||
|
# Run the compile.
|
||||||
|
"$@"
|
||||||
|
ret=$?
|
||||||
|
|
||||||
|
if test -f "$cofile"; then
|
||||||
|
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||||
|
elif test -f "${cofile}bj"; then
|
||||||
|
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rmdir "$lockdir"
|
||||||
|
exit $ret
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# mode: shell-script
|
||||||
|
# sh-indentation: 2
|
||||||
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC0"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
||||||
+1815
File diff suppressed because it is too large
Load Diff
+2354
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+247
@@ -0,0 +1,247 @@
|
|||||||
|
|
||||||
|
AC_INIT([mbase],[0.0.1])
|
||||||
|
AM_INIT_AUTOMAKE([foreign subdir-objects tar-pax])
|
||||||
|
AC_PREFIX_DEFAULT(/usr/local)
|
||||||
|
|
||||||
|
PACKAGE=mbase
|
||||||
|
|
||||||
|
AC_CHECK_PROG(HAVE_GO, go, true, false, [$PATH:/usr/local/bin])
|
||||||
|
if test "x$HAVE_GO" = "xfalse"; then
|
||||||
|
AC_MSG_ERROR([Requested program go not found])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_PATH_PROG([GO],[go],, [$PATH:/usr/local/bin])
|
||||||
|
|
||||||
|
AC_PATH_PROGS([CP],[gcp cp])
|
||||||
|
if test -z "$CP"; then
|
||||||
|
AC_MSG_ERROR([Requested program cp not found])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_PATH_PROGS([DBUILDPACKAGE],[dpkg-buildpackage true])
|
||||||
|
AC_PATH_PROGS([RPMBUILD],[rpmbuild true])
|
||||||
|
AC_PATH_PROGS([PROTOC],[protoc true])
|
||||||
|
AC_PATH_PROGS([PODMAN],[podman true])
|
||||||
|
AC_PATH_PROGS([CPIO],[cpio false])
|
||||||
|
AC_PATH_PROGS([XARGS],[xargs false])
|
||||||
|
AC_PATH_PROGS([PROTOC],[protoc false])
|
||||||
|
|
||||||
|
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
AC_PROG_MKDIR_P
|
||||||
|
AC_CANONICAL_HOST
|
||||||
|
AC_PROG_CC
|
||||||
|
|
||||||
|
dnl --------------------------------------------------------------------------------------
|
||||||
|
case $host_os in
|
||||||
|
*freebsd* )
|
||||||
|
AC_SUBST(ROOT_GROUP, "wheel")
|
||||||
|
AM_CONDITIONAL(FREEBSD_OS, true)
|
||||||
|
AM_CONDITIONAL(LINUX_OS, false)
|
||||||
|
OSNAME=freebsd
|
||||||
|
ROOT_GROUP=wheel
|
||||||
|
;;
|
||||||
|
*linux* )
|
||||||
|
AC_SUBST(ROOT_GROUP, "root")
|
||||||
|
AM_CONDITIONAL(FREEBSD_OS, false)
|
||||||
|
AM_CONDITIONAL(LINUX_OS, true)
|
||||||
|
OSNAME=linux
|
||||||
|
ROOT_GROUP=root
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
AM_CONDITIONAL(SYSTEMD, false)
|
||||||
|
if test -d /lib/systemd/system; then
|
||||||
|
AM_CONDITIONAL(SYSTEMD, true)
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
test "x$prefix" == "xNONE" && prefix=$ac_default_prefix
|
||||||
|
test "x$libexecdir" == "xNONE" && libexecdir=${prefix}/lib
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([devel-mode],
|
||||||
|
AS_HELP_STRING([--enable-devel-mode], [Enable developmend mode]))
|
||||||
|
|
||||||
|
|
||||||
|
AC_DEFINE_UNQUOTED(srv_devel_mode, "false", [developmend mode])
|
||||||
|
AC_SUBST(srv_devel_mode, "false")
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_devel_mode" = "xyes"], [
|
||||||
|
AC_DEFINE_UNQUOTED(srv_devel_mode, "true", [developmend mode])
|
||||||
|
AC_SUBST(srv_devel_mode, "true")
|
||||||
|
SRCDIR=`pwd`
|
||||||
|
enable_devel_mode=yes
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
dnl --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
SRV_CONFDIR=${prefix}/etc/${PACKAGE}
|
||||||
|
|
||||||
|
AC_ARG_WITH(confdir,
|
||||||
|
AS_HELP_STRING([--with-confdir=PATH],[set configuration dir to PATH (default: SRV_CONFDIR")]),
|
||||||
|
[ if test ! -z "$withval" ; then
|
||||||
|
case $withval in
|
||||||
|
/*)
|
||||||
|
SRV_CONFDIR="$withval"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
AC_MSG_ERROR(You must specify an absolute path to --with-confdir=PATH)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi ])
|
||||||
|
|
||||||
|
if test "x$prefix" == "x/usr"; then
|
||||||
|
SRV_CONFDIR=/etc/${PACKAGE}
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_devel_mode" = "xyes"], [
|
||||||
|
SRV_CONFDIR="${SRCDIR}/etc/${PACKAGE}"
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_DEFINE_UNQUOTED(SRV_CONFDIR, "$SRV_CONFDIR", [location of configuration files for ${PACKAGE}])
|
||||||
|
AC_SUBST(srv_confdir, "$SRV_CONFDIR")
|
||||||
|
AC_SUBST(SRV_CONFDIR, "$SRV_CONFDIR")
|
||||||
|
|
||||||
|
AC_MSG_NOTICE(srv_confdir set as ${SRV_CONFDIR})
|
||||||
|
|
||||||
|
dnl --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
SRV_LOGDIR="/var/log/${PACKAGE}"
|
||||||
|
|
||||||
|
AC_ARG_WITH(logdir,
|
||||||
|
AS_HELP_STRING([--with-logdir=PATH],[set file path for source logdir (default: $SRV_LOGDIR)]),
|
||||||
|
[ if test ! -z "$withval" ; then
|
||||||
|
case $withval in
|
||||||
|
/*)
|
||||||
|
SRV_LOGDIR="$withval"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
AC_MSG_ERROR(You must specify an absolute path to --with-logdir=PATH)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi ])
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_devel_mode" = "xyes"], [
|
||||||
|
SRV_LOGDIR="${SRCDIR}/tmp/log"
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
AC_DEFINE_UNQUOTED(SRV_LOGDIR, "$SRV_LOGDIR", [location of logdir])
|
||||||
|
AC_SUBST(srv_logdir, "$SRV_LOGDIR")
|
||||||
|
AC_SUBST(SRV_LOGDIR, "$SRV_LOGDIR")
|
||||||
|
|
||||||
|
AC_MSG_NOTICE(srv_logdir set as ${SRV_LOGDIR})
|
||||||
|
|
||||||
|
dnl --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
SRV_RUNDIR="/var/run/${PACKAGE}"
|
||||||
|
AC_ARG_WITH(rundir,
|
||||||
|
AS_HELP_STRING([--with-rundir=PATH],[set file path for source rundir (default: $SRV_RUNDIR)]),
|
||||||
|
[ if test ! -z "$withval" ; then
|
||||||
|
case $withval in
|
||||||
|
/*)
|
||||||
|
SRV_RUNDIR="$withval"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
AC_MSG_ERROR(You must specify an absolute path to --with-rundir=PATH)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi ])
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_devel_mode" = "xyes"], [
|
||||||
|
SRV_RUNDIR="${SRCDIR}/tmp/run"
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_DEFINE_UNQUOTED(SRV_RUNDIR, "$SRV_RUNDIR", [location of rundir])
|
||||||
|
AC_SUBST(srv_rundir, "$SRV_RUNDIR")
|
||||||
|
AC_SUBST(SRV_RUNDIR, "$SRV_RUNDIR")
|
||||||
|
|
||||||
|
AC_MSG_NOTICE(srv_rundir set as ${SRV_RUNDIR})
|
||||||
|
|
||||||
|
|
||||||
|
dnl --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
SRV_DATADIR="/var/data/${PACKAGE}"
|
||||||
|
AC_ARG_WITH(datadir,
|
||||||
|
AS_HELP_STRING([--with-datadir=PATH],[set file path for source datadir (default: $SRV_DATADIR)]),
|
||||||
|
[ if test ! -z "$withval" ; then
|
||||||
|
case $withval in
|
||||||
|
/*)
|
||||||
|
SRV_DATADIR="$withval"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
AC_MSG_ERROR(You must specify an absolute path to --with-datadir=PATH)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi ])
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_devel_mode" = "xyes"], [
|
||||||
|
SRV_DATADIR="${SRCDIR}/tmp/data"
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_DEFINE_UNQUOTED(SRV_DATADIR, "$SRV_DATADIR", [location of datadir])
|
||||||
|
AC_SUBST(srv_datadir, "$SRV_DATADIR")
|
||||||
|
AC_SUBST(SRV_DATADIR, "$SRV_DATADIR")
|
||||||
|
|
||||||
|
AC_MSG_NOTICE(srv_datadir set as ${SRV_DATADIR})
|
||||||
|
|
||||||
|
dnl --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
AM_CONDITIONAL(MAKEALL, true)
|
||||||
|
AM_CONDITIONAL(MAKESERVICE, true)
|
||||||
|
AM_CONDITIONAL(MAKECONTROL, true)
|
||||||
|
AM_CONDITIONAL(MAKECONTAINER, false)
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_devel_mode" = "xyes"], [
|
||||||
|
AM_CONDITIONAL(DEV_MODE, true)
|
||||||
|
],[
|
||||||
|
AM_CONDITIONAL(DEV_MODE, false)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([only-service], AS_HELP_STRING([--enable-only-service], [Compile only service part]),
|
||||||
|
[
|
||||||
|
AM_CONDITIONAL(MAKEALL, false)
|
||||||
|
AM_CONDITIONAL(MAKECONTROL, false)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([only-control], AS_HELP_STRING([--enable-only-control], [Compile only control part]),
|
||||||
|
[
|
||||||
|
AM_CONDITIONAL(MAKEALL, false)
|
||||||
|
AM_CONDITIONAL(MAKECONTROL, true)
|
||||||
|
AM_CONDITIONAL(MAKESERVICE, false)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([container-mode], AS_HELP_STRING([--enable-container-mode], [Compile only service part wo tools]),
|
||||||
|
[
|
||||||
|
AM_CONDITIONAL(MAKEALL, false)
|
||||||
|
AM_CONDITIONAL(MAKESERVICE, true)
|
||||||
|
AM_CONDITIONAL(MAKECONTAINER, true)
|
||||||
|
AM_CONDITIONAL(MAKECONTROL, false)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_only_service" = "xyes" && test "x$enable_only_control" = "xyes"],
|
||||||
|
AM_CONDITIONAL(MAKEALL, true)
|
||||||
|
AM_CONDITIONAL(MAKESERVICE, true)
|
||||||
|
)
|
||||||
|
|
||||||
|
dnl AS_IF([test "x$enable_only_control" = "xyes"],
|
||||||
|
dnl AM_CONDITIONAL(INSTALLRC, false)
|
||||||
|
dnl )
|
||||||
|
|
||||||
|
AC_SUBST(srv_name, "$PACKAGE")
|
||||||
|
AC_SUBST(srv_sbindir, "${prefix}/sbin")
|
||||||
|
|
||||||
|
|
||||||
|
AC_CONFIG_FILES([
|
||||||
|
Makefile
|
||||||
|
app/config/variant.go
|
||||||
|
initrc/mbased.service
|
||||||
|
initrc/mbased
|
||||||
|
])
|
||||||
|
AC_OUTPUT
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
daemon: false
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
module mbase
|
||||||
|
|
||||||
|
go 1.26.2
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gin-gonic/gin v1.12.0
|
||||||
|
github.com/jmoiron/sqlx v1.4.0
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.44
|
||||||
|
github.com/sirupsen/logrus v1.9.4
|
||||||
|
github.com/spf13/cobra v1.10.2
|
||||||
|
github.com/stretchr/testify v1.11.1
|
||||||
|
go.yaml.in/yaml/v4 v4.0.0-rc.4
|
||||||
|
google.golang.org/grpc v1.81.1
|
||||||
|
google.golang.org/protobuf v1.36.11
|
||||||
|
sigs.k8s.io/yaml v1.6.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/bytedance/gopkg v0.1.3 // indirect
|
||||||
|
github.com/bytedance/sonic v1.15.0 // indirect
|
||||||
|
github.com/bytedance/sonic/loader v0.5.0 // indirect
|
||||||
|
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.12 // indirect
|
||||||
|
github.com/gin-contrib/sse v1.1.0 // indirect
|
||||||
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
|
github.com/go-playground/validator/v10 v10.30.1 // indirect
|
||||||
|
github.com/goccy/go-json v0.10.5 // indirect
|
||||||
|
github.com/goccy/go-yaml v1.19.2 // indirect
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||||
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/quic-go/qpack v0.6.0 // indirect
|
||||||
|
github.com/quic-go/quic-go v0.59.0 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.9 // indirect
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
|
github.com/ugorji/go/codec v1.3.1 // indirect
|
||||||
|
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
|
||||||
|
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||||
|
golang.org/x/arch v0.22.0 // indirect
|
||||||
|
golang.org/x/crypto v0.48.0 // indirect
|
||||||
|
golang.org/x/net v0.51.0 // indirect
|
||||||
|
golang.org/x/sys v0.42.0 // indirect
|
||||||
|
golang.org/x/text v0.34.0 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||||
|
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||||
|
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
|
||||||
|
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
|
||||||
|
github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE=
|
||||||
|
github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k=
|
||||||
|
github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE=
|
||||||
|
github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
|
||||||
|
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||||
|
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
|
||||||
|
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
||||||
|
github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8=
|
||||||
|
github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc=
|
||||||
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
|
github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w=
|
||||||
|
github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM=
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||||
|
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||||
|
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||||
|
github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
|
||||||
|
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||||
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
|
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
|
||||||
|
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
|
||||||
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||||
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
|
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||||
|
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||||
|
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.44 h1:3VSe+xafpbzsLbdr2AWlAZk9yRHiBhTBakioXaCKTF8=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.44/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||||
|
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||||
|
github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
|
||||||
|
github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||||
|
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||||
|
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
|
||||||
|
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
|
||||||
|
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
|
||||||
|
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
|
||||||
|
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
|
||||||
|
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
|
github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY=
|
||||||
|
github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||||
|
go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE=
|
||||||
|
go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||||
|
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
|
||||||
|
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
|
||||||
|
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
|
||||||
|
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
|
||||||
|
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
|
||||||
|
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
|
||||||
|
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||||
|
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||||
|
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
|
||||||
|
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
||||||
|
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||||
|
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||||
|
go.yaml.in/yaml/v4 v4.0.0-rc.4 h1:UP4+v6fFrBIb1l934bDl//mmnoIZEDK0idg1+AIvX5U=
|
||||||
|
go.yaml.in/yaml/v4 v4.0.0-rc.4/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
|
||||||
|
golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI=
|
||||||
|
golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
|
||||||
|
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||||
|
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||||
|
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
|
||||||
|
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||||
|
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
|
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||||
|
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||||
|
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||||
|
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||||
|
google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
|
||||||
|
google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
|
||||||
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
|
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
|
||||||
|
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# PROVIDE: mbased
|
||||||
|
# REQUIRE: DAEMON
|
||||||
|
|
||||||
|
. /etc/rc.subr
|
||||||
|
|
||||||
|
name="mbased"
|
||||||
|
rcvar="mbased_enable"
|
||||||
|
|
||||||
|
pidfile="@srv_rundir@"/mbased.pid
|
||||||
|
command="@prefix@/sbin/${name}"
|
||||||
|
command_args="-daemon"
|
||||||
|
procname="@prefix@/sbin/${name}"
|
||||||
|
|
||||||
|
load_rc_config ${name}
|
||||||
|
|
||||||
|
: ${mbased_enable:="NO"}
|
||||||
|
|
||||||
|
run_rc_command "$1"
|
||||||
|
#EOF
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=mbased
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=forking
|
||||||
|
ExecStart=@srv_sbindir@/mbased
|
||||||
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
|
ExecRestart=/bin/kill -HUP $MAINPID
|
||||||
|
ExecStartPre=/usr/bin/install -d -o root -g root @srv_rundir@ @srv_logdir@ @srv_datadir@
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
|
||||||
Executable
+541
@@ -0,0 +1,541 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# install - install a program, script, or datafile
|
||||||
|
|
||||||
|
scriptversion=2024-06-19.01; # UTC
|
||||||
|
|
||||||
|
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||||
|
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||||
|
# following copyright and license.
|
||||||
|
#
|
||||||
|
# Copyright (C) 1994 X Consortium
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to
|
||||||
|
# deal in the Software without restriction, including without limitation the
|
||||||
|
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
# sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||||
|
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
#
|
||||||
|
# Except as contained in this notice, the name of the X Consortium shall not
|
||||||
|
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||||
|
# ings in this Software without prior written authorization from the X Consor-
|
||||||
|
# tium.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# FSF changes to this file are in the public domain.
|
||||||
|
#
|
||||||
|
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||||
|
# 'make' implicit rules from creating a file called install from it
|
||||||
|
# when there is no Makefile.
|
||||||
|
#
|
||||||
|
# This script is compatible with the BSD install script, but was written
|
||||||
|
# from scratch.
|
||||||
|
|
||||||
|
tab=' '
|
||||||
|
nl='
|
||||||
|
'
|
||||||
|
IFS=" $tab$nl"
|
||||||
|
|
||||||
|
# Set DOITPROG to "echo" to test this script.
|
||||||
|
|
||||||
|
doit=${DOITPROG-}
|
||||||
|
doit_exec=${doit:-exec}
|
||||||
|
|
||||||
|
# Put in absolute file names if you don't have them in your path;
|
||||||
|
# or use environment vars.
|
||||||
|
|
||||||
|
chgrpprog=${CHGRPPROG-chgrp}
|
||||||
|
chmodprog=${CHMODPROG-chmod}
|
||||||
|
chownprog=${CHOWNPROG-chown}
|
||||||
|
cmpprog=${CMPPROG-cmp}
|
||||||
|
cpprog=${CPPROG-cp}
|
||||||
|
mkdirprog=${MKDIRPROG-mkdir}
|
||||||
|
mvprog=${MVPROG-mv}
|
||||||
|
rmprog=${RMPROG-rm}
|
||||||
|
stripprog=${STRIPPROG-strip}
|
||||||
|
|
||||||
|
posix_mkdir=
|
||||||
|
|
||||||
|
# Desired mode of installed file.
|
||||||
|
mode=0755
|
||||||
|
|
||||||
|
# Create dirs (including intermediate dirs) using mode 755.
|
||||||
|
# This is like GNU 'install' as of coreutils 8.32 (2020).
|
||||||
|
mkdir_umask=22
|
||||||
|
|
||||||
|
backupsuffix=
|
||||||
|
chgrpcmd=
|
||||||
|
chmodcmd=$chmodprog
|
||||||
|
chowncmd=
|
||||||
|
mvcmd=$mvprog
|
||||||
|
rmcmd="$rmprog -f"
|
||||||
|
stripcmd=
|
||||||
|
|
||||||
|
src=
|
||||||
|
dst=
|
||||||
|
dir_arg=
|
||||||
|
dst_arg=
|
||||||
|
|
||||||
|
copy_on_change=false
|
||||||
|
is_target_a_directory=possibly
|
||||||
|
|
||||||
|
usage="\
|
||||||
|
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||||
|
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||||
|
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||||
|
or: $0 [OPTION]... -d DIRECTORIES...
|
||||||
|
|
||||||
|
In the 1st form, copy SRCFILE to DSTFILE.
|
||||||
|
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||||
|
In the 4th, create DIRECTORIES.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--help display this help and exit.
|
||||||
|
--version display version info and exit.
|
||||||
|
|
||||||
|
-c (ignored)
|
||||||
|
-C install only if different (preserve data modification time)
|
||||||
|
-d create directories instead of installing files.
|
||||||
|
-g GROUP $chgrpprog installed files to GROUP.
|
||||||
|
-m MODE $chmodprog installed files to MODE.
|
||||||
|
-o USER $chownprog installed files to USER.
|
||||||
|
-p pass -p to $cpprog.
|
||||||
|
-s $stripprog installed files.
|
||||||
|
-S SUFFIX attempt to back up existing files, with suffix SUFFIX.
|
||||||
|
-t DIRECTORY install into DIRECTORY.
|
||||||
|
-T report an error if DSTFILE is a directory.
|
||||||
|
|
||||||
|
Environment variables override the default commands:
|
||||||
|
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||||
|
RMPROG STRIPPROG
|
||||||
|
|
||||||
|
By default, rm is invoked with -f; when overridden with RMPROG,
|
||||||
|
it's up to you to specify -f if you want it.
|
||||||
|
|
||||||
|
If -S is not specified, no backups are attempted.
|
||||||
|
|
||||||
|
Report bugs to <bug-automake@gnu.org>.
|
||||||
|
GNU Automake home page: <https://www.gnu.org/software/automake/>.
|
||||||
|
General help using GNU software: <https://www.gnu.org/gethelp/>."
|
||||||
|
|
||||||
|
while test $# -ne 0; do
|
||||||
|
case $1 in
|
||||||
|
-c) ;;
|
||||||
|
|
||||||
|
-C) copy_on_change=true;;
|
||||||
|
|
||||||
|
-d) dir_arg=true;;
|
||||||
|
|
||||||
|
-g) chgrpcmd="$chgrpprog $2"
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
--help) echo "$usage"; exit $?;;
|
||||||
|
|
||||||
|
-m) mode=$2
|
||||||
|
case $mode in
|
||||||
|
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
|
||||||
|
echo "$0: invalid mode: $mode" >&2
|
||||||
|
exit 1;;
|
||||||
|
esac
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-o) chowncmd="$chownprog $2"
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-p) cpprog="$cpprog -p";;
|
||||||
|
|
||||||
|
-s) stripcmd=$stripprog;;
|
||||||
|
|
||||||
|
-S) backupsuffix="$2"
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-t)
|
||||||
|
is_target_a_directory=always
|
||||||
|
dst_arg=$2
|
||||||
|
# Protect names problematic for 'test' and other utilities.
|
||||||
|
case $dst_arg in
|
||||||
|
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||||
|
esac
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-T) is_target_a_directory=never;;
|
||||||
|
|
||||||
|
--version) echo "$0 (GNU Automake) $scriptversion"; exit $?;;
|
||||||
|
|
||||||
|
--) shift
|
||||||
|
break;;
|
||||||
|
|
||||||
|
-*) echo "$0: invalid option: $1" >&2
|
||||||
|
exit 1;;
|
||||||
|
|
||||||
|
*) break;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
# We allow the use of options -d and -T together, by making -d
|
||||||
|
# take the precedence; this is for compatibility with GNU install.
|
||||||
|
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
if test -n "$dst_arg"; then
|
||||||
|
echo "$0: target directory not allowed when installing a directory." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||||
|
# When -d is used, all remaining arguments are directories to create.
|
||||||
|
# When -t is used, the destination is already specified.
|
||||||
|
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
if test -n "$dst_arg"; then
|
||||||
|
# $@ is not empty: it contains at least $arg.
|
||||||
|
set fnord "$@" "$dst_arg"
|
||||||
|
shift # fnord
|
||||||
|
fi
|
||||||
|
shift # arg
|
||||||
|
dst_arg=$arg
|
||||||
|
# Protect names problematic for 'test' and other utilities.
|
||||||
|
case $dst_arg in
|
||||||
|
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $# -eq 0; then
|
||||||
|
if test -z "$dir_arg"; then
|
||||||
|
echo "$0: no input file specified." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# It's OK to call 'install-sh -d' without argument.
|
||||||
|
# This can happen when creating conditional directories.
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$dir_arg"; then
|
||||||
|
if test $# -gt 1 || test "$is_target_a_directory" = always; then
|
||||||
|
if test ! -d "$dst_arg"; then
|
||||||
|
echo "$0: $dst_arg: Is not a directory." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$dir_arg"; then
|
||||||
|
do_exit='(exit $ret); exit $ret'
|
||||||
|
trap "ret=129; $do_exit" 1
|
||||||
|
trap "ret=130; $do_exit" 2
|
||||||
|
trap "ret=141; $do_exit" 13
|
||||||
|
trap "ret=143; $do_exit" 15
|
||||||
|
|
||||||
|
# Set umask so as not to create temps with too-generous modes.
|
||||||
|
# However, 'strip' requires both read and write access to temps.
|
||||||
|
case $mode in
|
||||||
|
# Optimize common cases.
|
||||||
|
*644) cp_umask=133;;
|
||||||
|
*755) cp_umask=22;;
|
||||||
|
|
||||||
|
*[0-7])
|
||||||
|
if test -z "$stripcmd"; then
|
||||||
|
u_plus_rw=
|
||||||
|
else
|
||||||
|
u_plus_rw='% 200'
|
||||||
|
fi
|
||||||
|
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||||
|
*)
|
||||||
|
if test -z "$stripcmd"; then
|
||||||
|
u_plus_rw=
|
||||||
|
else
|
||||||
|
u_plus_rw=,u+rw
|
||||||
|
fi
|
||||||
|
cp_umask=$mode$u_plus_rw;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
for src
|
||||||
|
do
|
||||||
|
# Protect names problematic for 'test' and other utilities.
|
||||||
|
case $src in
|
||||||
|
-* | [=\(\)!]) src=./$src;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
dst=$src
|
||||||
|
dstdir=$dst
|
||||||
|
test -d "$dstdir"
|
||||||
|
dstdir_status=$?
|
||||||
|
# Don't chown directories that already exist.
|
||||||
|
if test $dstdir_status = 0; then
|
||||||
|
chowncmd=""
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
|
||||||
|
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||||
|
# might cause directories to be created, which would be especially bad
|
||||||
|
# if $src (and thus $dsttmp) contains '*'.
|
||||||
|
if test ! -f "$src" && test ! -d "$src"; then
|
||||||
|
echo "$0: $src does not exist." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$dst_arg"; then
|
||||||
|
echo "$0: no destination specified." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
dst=$dst_arg
|
||||||
|
|
||||||
|
# If destination is a directory, append the input filename.
|
||||||
|
if test -d "$dst"; then
|
||||||
|
if test "$is_target_a_directory" = never; then
|
||||||
|
echo "$0: $dst_arg: Is a directory" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
dstdir=$dst
|
||||||
|
dstbase=`basename "$src"`
|
||||||
|
case $dst in
|
||||||
|
*/) dst=$dst$dstbase;;
|
||||||
|
*) dst=$dst/$dstbase;;
|
||||||
|
esac
|
||||||
|
dstdir_status=0
|
||||||
|
else
|
||||||
|
dstdir=`dirname "$dst"`
|
||||||
|
test -d "$dstdir"
|
||||||
|
dstdir_status=$?
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $dstdir in
|
||||||
|
*/) dstdirslash=$dstdir;;
|
||||||
|
*) dstdirslash=$dstdir/;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
obsolete_mkdir_used=false
|
||||||
|
|
||||||
|
if test $dstdir_status != 0; then
|
||||||
|
case $posix_mkdir in
|
||||||
|
'')
|
||||||
|
# With -d, create the new directory with the user-specified mode.
|
||||||
|
# Otherwise, rely on $mkdir_umask.
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
mkdir_mode=-m$mode
|
||||||
|
else
|
||||||
|
mkdir_mode=
|
||||||
|
fi
|
||||||
|
|
||||||
|
posix_mkdir=false
|
||||||
|
# The $RANDOM variable is not portable (e.g., dash). Use it
|
||||||
|
# here however when possible just to lower collision chance.
|
||||||
|
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||||
|
|
||||||
|
trap '
|
||||||
|
ret=$?
|
||||||
|
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
|
||||||
|
exit $ret
|
||||||
|
' 0
|
||||||
|
|
||||||
|
# Because "mkdir -p" follows existing symlinks and we likely work
|
||||||
|
# directly in world-writable /tmp, make sure that the '$tmpdir'
|
||||||
|
# directory is successfully created first before we actually test
|
||||||
|
# 'mkdir -p'.
|
||||||
|
if (umask $mkdir_umask &&
|
||||||
|
$mkdirprog $mkdir_mode "$tmpdir" &&
|
||||||
|
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
if test -z "$dir_arg" || {
|
||||||
|
# Check for POSIX incompatibility with -m.
|
||||||
|
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||||
|
# other-writable bit of parent directory when it shouldn't.
|
||||||
|
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||||
|
test_tmpdir="$tmpdir/a"
|
||||||
|
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
|
||||||
|
case $ls_ld_tmpdir in
|
||||||
|
d????-?r-*) different_mode=700;;
|
||||||
|
d????-?--*) different_mode=755;;
|
||||||
|
*) false;;
|
||||||
|
esac &&
|
||||||
|
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
|
||||||
|
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
|
||||||
|
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
then posix_mkdir=:
|
||||||
|
fi
|
||||||
|
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
|
||||||
|
else
|
||||||
|
# Remove any dirs left behind by ancient mkdir implementations.
|
||||||
|
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
|
||||||
|
fi
|
||||||
|
trap '' 0;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if
|
||||||
|
$posix_mkdir && (
|
||||||
|
umask $mkdir_umask &&
|
||||||
|
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||||
|
)
|
||||||
|
then :
|
||||||
|
else
|
||||||
|
|
||||||
|
# mkdir does not conform to POSIX,
|
||||||
|
# or it failed possibly due to a race condition. Create the
|
||||||
|
# directory the slow way, step by step, checking for races as we go.
|
||||||
|
|
||||||
|
case $dstdir in
|
||||||
|
/*) prefix='/';;
|
||||||
|
[-=\(\)!]*) prefix='./';;
|
||||||
|
*) prefix='';;
|
||||||
|
esac
|
||||||
|
|
||||||
|
oIFS=$IFS
|
||||||
|
IFS=/
|
||||||
|
set -f
|
||||||
|
set fnord $dstdir
|
||||||
|
shift
|
||||||
|
set +f
|
||||||
|
IFS=$oIFS
|
||||||
|
|
||||||
|
prefixes=
|
||||||
|
|
||||||
|
for d
|
||||||
|
do
|
||||||
|
test X"$d" = X && continue
|
||||||
|
|
||||||
|
prefix=$prefix$d
|
||||||
|
if test -d "$prefix"; then
|
||||||
|
prefixes=
|
||||||
|
else
|
||||||
|
if $posix_mkdir; then
|
||||||
|
(umask $mkdir_umask &&
|
||||||
|
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||||
|
# Don't fail if two instances are running concurrently.
|
||||||
|
test -d "$prefix" || exit 1
|
||||||
|
else
|
||||||
|
case $prefix in
|
||||||
|
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||||
|
*) qprefix=$prefix;;
|
||||||
|
esac
|
||||||
|
prefixes="$prefixes '$qprefix'"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
prefix=$prefix/
|
||||||
|
done
|
||||||
|
|
||||||
|
if test -n "$prefixes"; then
|
||||||
|
# Don't fail if two instances are running concurrently.
|
||||||
|
(umask $mkdir_umask &&
|
||||||
|
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||||
|
test -d "$dstdir" || exit 1
|
||||||
|
obsolete_mkdir_used=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||||
|
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||||
|
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||||
|
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||||
|
else
|
||||||
|
|
||||||
|
# Make a couple of temp file names in the proper directory.
|
||||||
|
dsttmp=${dstdirslash}_inst.$$_
|
||||||
|
rmtmp=${dstdirslash}_rm.$$_
|
||||||
|
|
||||||
|
# Trap to clean up those temp files at exit.
|
||||||
|
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||||
|
|
||||||
|
# Copy the file name to the temp name.
|
||||||
|
(umask $cp_umask &&
|
||||||
|
{ test -z "$stripcmd" || {
|
||||||
|
# Create $dsttmp read-write so that cp doesn't create it read-only,
|
||||||
|
# which would cause strip to fail.
|
||||||
|
if test -z "$doit"; then
|
||||||
|
: >"$dsttmp" # No need to fork-exec 'touch'.
|
||||||
|
else
|
||||||
|
$doit touch "$dsttmp"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
} &&
|
||||||
|
$doit_exec $cpprog "$src" "$dsttmp") &&
|
||||||
|
|
||||||
|
# and set any options; do chmod last to preserve setuid bits.
|
||||||
|
#
|
||||||
|
# If any of these fail, we abort the whole thing. If we want to
|
||||||
|
# ignore errors from any of these, just make sure not to ignore
|
||||||
|
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||||
|
#
|
||||||
|
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||||
|
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||||
|
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||||
|
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||||
|
|
||||||
|
# If -C, don't bother to copy if it wouldn't change the file.
|
||||||
|
if $copy_on_change &&
|
||||||
|
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||||
|
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||||
|
set -f &&
|
||||||
|
set X $old && old=:$2:$4:$5:$6 &&
|
||||||
|
set X $new && new=:$2:$4:$5:$6 &&
|
||||||
|
set +f &&
|
||||||
|
test "$old" = "$new" &&
|
||||||
|
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
rm -f "$dsttmp"
|
||||||
|
else
|
||||||
|
# If $backupsuffix is set, and the file being installed
|
||||||
|
# already exists, attempt a backup. Don't worry if it fails,
|
||||||
|
# e.g., if mv doesn't support -f.
|
||||||
|
if test -n "$backupsuffix" && test -f "$dst"; then
|
||||||
|
$doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Rename the file to the real destination.
|
||||||
|
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||||
|
|
||||||
|
# The rename failed, perhaps because mv can't rename something else
|
||||||
|
# to itself, or perhaps because mv is so ancient that it does not
|
||||||
|
# support -f.
|
||||||
|
{
|
||||||
|
# Now remove or move aside any old file at destination location.
|
||||||
|
# We try this two ways since rm can't unlink itself on some
|
||||||
|
# systems and the destination file might be busy for other
|
||||||
|
# reasons. In this case, the final cleanup might fail but the new
|
||||||
|
# file should still install successfully.
|
||||||
|
{
|
||||||
|
test ! -f "$dst" ||
|
||||||
|
$doit $rmcmd "$dst" 2>/dev/null ||
|
||||||
|
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||||
|
{ $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
|
||||||
|
} ||
|
||||||
|
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||||
|
(exit 1); exit 1
|
||||||
|
}
|
||||||
|
} &&
|
||||||
|
|
||||||
|
# Now rename the file to the real destination.
|
||||||
|
$doit $mvcmd "$dsttmp" "$dst"
|
||||||
|
}
|
||||||
|
fi || exit 1
|
||||||
|
|
||||||
|
trap '' 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Local variables:
|
||||||
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC0"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
||||||
@@ -0,0 +1,236 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
# Common wrapper for a few potentially missing GNU and other programs.
|
||||||
|
|
||||||
|
scriptversion=2024-06-07.14; # UTC
|
||||||
|
|
||||||
|
# shellcheck disable=SC2006,SC2268 # we must support pre-POSIX shells
|
||||||
|
|
||||||
|
# Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||||
|
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# As a special exception to the GNU General Public License, if you
|
||||||
|
# distribute this file as part of a program that contains a
|
||||||
|
# configuration script generated by Autoconf, you may include it under
|
||||||
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
if test $# -eq 0; then
|
||||||
|
echo 1>&2 "Try '$0 --help' for more information"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
|
||||||
|
--is-lightweight)
|
||||||
|
# Used by our autoconf macros to check whether the available missing
|
||||||
|
# script is modern enough.
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--run)
|
||||||
|
# Back-compat with the calling convention used by older automake.
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
|
||||||
|
-h|--h|--he|--hel|--help)
|
||||||
|
echo "\
|
||||||
|
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||||
|
|
||||||
|
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
|
||||||
|
to PROGRAM being missing or too old.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h, --help display this help and exit
|
||||||
|
-v, --version output version information and exit
|
||||||
|
|
||||||
|
Supported PROGRAM values:
|
||||||
|
aclocal autoconf autogen autoheader autom4te automake autoreconf
|
||||||
|
bison flex help2man lex makeinfo perl yacc
|
||||||
|
|
||||||
|
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
|
||||||
|
'g' are ignored when checking the name.
|
||||||
|
|
||||||
|
Report bugs to <bug-automake@gnu.org>.
|
||||||
|
GNU Automake home page: <https://www.gnu.org/software/automake/>.
|
||||||
|
General help using GNU software: <https://www.gnu.org/gethelp/>."
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
|
||||||
|
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||||
|
echo "missing (GNU Automake) $scriptversion"
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
|
||||||
|
-*)
|
||||||
|
echo 1>&2 "$0: unknown '$1' option"
|
||||||
|
echo 1>&2 "Try '$0 --help' for more information"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Run the given program, remember its exit status.
|
||||||
|
"$@"; st=$?
|
||||||
|
|
||||||
|
# If it succeeded, we are done.
|
||||||
|
test $st -eq 0 && exit 0
|
||||||
|
|
||||||
|
# Also exit now if we it failed (or wasn't found), and '--version' was
|
||||||
|
# passed; such an option is passed most likely to detect whether the
|
||||||
|
# program is present and works.
|
||||||
|
case $2 in --version|--help) exit $st;; esac
|
||||||
|
|
||||||
|
# Exit code 63 means version mismatch. This often happens when the user
|
||||||
|
# tries to use an ancient version of a tool on a file that requires a
|
||||||
|
# minimum version.
|
||||||
|
if test $st -eq 63; then
|
||||||
|
msg="probably too old"
|
||||||
|
elif test $st -eq 127; then
|
||||||
|
# Program was missing.
|
||||||
|
msg="missing on your system"
|
||||||
|
else
|
||||||
|
# Program was found and executed, but failed. Give up.
|
||||||
|
exit $st
|
||||||
|
fi
|
||||||
|
|
||||||
|
perl_URL=https://www.perl.org/
|
||||||
|
flex_URL=https://github.com/westes/flex
|
||||||
|
gnu_software_URL=https://www.gnu.org/software
|
||||||
|
|
||||||
|
program_details ()
|
||||||
|
{
|
||||||
|
case $1 in
|
||||||
|
aclocal|automake|autoreconf)
|
||||||
|
echo "The '$1' program is part of the GNU Automake package:"
|
||||||
|
echo "<$gnu_software_URL/automake>"
|
||||||
|
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
|
||||||
|
echo "<$gnu_software_URL/autoconf>"
|
||||||
|
echo "<$gnu_software_URL/m4/>"
|
||||||
|
echo "<$perl_URL>"
|
||||||
|
;;
|
||||||
|
autoconf|autom4te|autoheader)
|
||||||
|
echo "The '$1' program is part of the GNU Autoconf package:"
|
||||||
|
echo "<$gnu_software_URL/autoconf/>"
|
||||||
|
echo "It also requires GNU m4 and Perl in order to run:"
|
||||||
|
echo "<$gnu_software_URL/m4/>"
|
||||||
|
echo "<$perl_URL>"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
:
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
give_advice ()
|
||||||
|
{
|
||||||
|
# Normalize program name to check for.
|
||||||
|
normalized_program=`echo "$1" | sed '
|
||||||
|
s/^gnu-//; t
|
||||||
|
s/^gnu//; t
|
||||||
|
s/^g//; t'`
|
||||||
|
|
||||||
|
printf '%s\n' "'$1' is $msg."
|
||||||
|
|
||||||
|
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
|
||||||
|
autoheader_deps="'acconfig.h'"
|
||||||
|
automake_deps="'Makefile.am'"
|
||||||
|
aclocal_deps="'acinclude.m4'"
|
||||||
|
case $normalized_program in
|
||||||
|
aclocal*)
|
||||||
|
echo "You should only need it if you modified $aclocal_deps or"
|
||||||
|
echo "$configure_deps."
|
||||||
|
;;
|
||||||
|
autoconf*)
|
||||||
|
echo "You should only need it if you modified $configure_deps."
|
||||||
|
;;
|
||||||
|
autogen*)
|
||||||
|
echo "You should only need it if you modified a '.def' or '.tpl' file."
|
||||||
|
echo "You may want to install the GNU AutoGen package:"
|
||||||
|
echo "<$gnu_software_URL/autogen/>"
|
||||||
|
;;
|
||||||
|
autoheader*)
|
||||||
|
echo "You should only need it if you modified $autoheader_deps or"
|
||||||
|
echo "$configure_deps."
|
||||||
|
;;
|
||||||
|
automake*)
|
||||||
|
echo "You should only need it if you modified $automake_deps or"
|
||||||
|
echo "$configure_deps."
|
||||||
|
;;
|
||||||
|
autom4te*)
|
||||||
|
echo "You might have modified some maintainer files that require"
|
||||||
|
echo "the 'autom4te' program to be rebuilt."
|
||||||
|
;;
|
||||||
|
autoreconf*)
|
||||||
|
echo "You should only need it if you modified $aclocal_deps or"
|
||||||
|
echo "$automake_deps or $autoheader_deps or $automake_deps or"
|
||||||
|
echo "$configure_deps."
|
||||||
|
;;
|
||||||
|
bison*|yacc*)
|
||||||
|
echo "You should only need it if you modified a '.y' file."
|
||||||
|
echo "You may want to install the GNU Bison package:"
|
||||||
|
echo "<$gnu_software_URL/bison/>"
|
||||||
|
;;
|
||||||
|
help2man*)
|
||||||
|
echo "You should only need it if you modified a dependency" \
|
||||||
|
"of a man page."
|
||||||
|
echo "You may want to install the GNU Help2man package:"
|
||||||
|
echo "<$gnu_software_URL/help2man/>"
|
||||||
|
;;
|
||||||
|
lex*|flex*)
|
||||||
|
echo "You should only need it if you modified a '.l' file."
|
||||||
|
echo "You may want to install the Fast Lexical Analyzer package:"
|
||||||
|
echo "<$flex_URL>"
|
||||||
|
;;
|
||||||
|
makeinfo*)
|
||||||
|
echo "You should only need it if you modified a '.texi' file, or"
|
||||||
|
echo "any other file indirectly affecting the aspect of the manual."
|
||||||
|
echo "You might want to install the Texinfo package:"
|
||||||
|
echo "<$gnu_software_URL/texinfo/>"
|
||||||
|
echo "The spurious makeinfo call might also be the consequence of"
|
||||||
|
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
|
||||||
|
echo "want to install GNU make:"
|
||||||
|
echo "<$gnu_software_URL/make/>"
|
||||||
|
;;
|
||||||
|
perl*)
|
||||||
|
echo "You should only need it to run GNU Autoconf, GNU Automake, "
|
||||||
|
echo " assorted other tools, or if you modified a Perl source file."
|
||||||
|
echo "You may want to install the Perl 5 language interpreter:"
|
||||||
|
echo "<$perl_URL>"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "You might have modified some files without having the proper"
|
||||||
|
echo "tools for further handling them. Check the 'README' file, it"
|
||||||
|
echo "often tells you about the needed prerequisites for installing"
|
||||||
|
echo "this package. You may also peek at any GNU archive site, in"
|
||||||
|
echo "case some other package contains this missing '$1' program."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
program_details "$normalized_program"
|
||||||
|
}
|
||||||
|
|
||||||
|
give_advice "$1" | sed -e '1s/^/WARNING: /' \
|
||||||
|
-e '2,$s/^/ /' >&2
|
||||||
|
|
||||||
|
# Propagate the correct exit status (expected to be 127 for a program
|
||||||
|
# not found, 63 for a program that failed due to version mismatch).
|
||||||
|
exit $st
|
||||||
|
|
||||||
|
# Local variables:
|
||||||
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC0"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
package aux509
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"encoding/pem"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CreateX509SelfSignedCert(subject string, hostNames ...string) ([]byte, []byte, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
certPem := make([]byte, 0)
|
||||||
|
keyPem := make([]byte, 0)
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
const yearsAfter int = 10
|
||||||
|
const keySize int = 2048
|
||||||
|
|
||||||
|
key, err := rsa.GenerateKey(rand.Reader, keySize)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("Can't create a private key: %v", err)
|
||||||
|
return certPem, keyPem, err
|
||||||
|
|
||||||
|
}
|
||||||
|
keyPemBlock := pem.Block{
|
||||||
|
Type: "RSA PRIVATE KEY",
|
||||||
|
Bytes: x509.MarshalPKCS1PrivateKey(key),
|
||||||
|
}
|
||||||
|
keyPem = pem.EncodeToMemory(&keyPemBlock)
|
||||||
|
|
||||||
|
certSubject := pkix.Name{
|
||||||
|
CommonName: subject,
|
||||||
|
}
|
||||||
|
certIssuer := certSubject
|
||||||
|
|
||||||
|
dnsNames := make([]string, 0)
|
||||||
|
dnsNames = append(dnsNames, subject)
|
||||||
|
dnsNames = append(dnsNames, hostNames...)
|
||||||
|
tml := x509.Certificate{
|
||||||
|
SerialNumber: big.NewInt(now.Unix()),
|
||||||
|
NotBefore: now,
|
||||||
|
NotAfter: now.AddDate(yearsAfter, 0, 0),
|
||||||
|
Subject: certSubject,
|
||||||
|
Issuer: certIssuer,
|
||||||
|
DNSNames: dnsNames,
|
||||||
|
BasicConstraintsValid: true,
|
||||||
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
|
||||||
|
KeyUsage: x509.KeyUsageDigitalSignature |
|
||||||
|
x509.KeyUsageContentCommitment |
|
||||||
|
x509.KeyUsageKeyEncipherment |
|
||||||
|
x509.KeyUsageDataEncipherment,
|
||||||
|
}
|
||||||
|
certBytes, err := x509.CreateCertificate(rand.Reader, &tml, &tml, &key.PublicKey, key)
|
||||||
|
if err != nil {
|
||||||
|
return certPem, keyPem, fmt.Errorf("Can't create a certificate: %v", err)
|
||||||
|
|
||||||
|
}
|
||||||
|
certPemBlock := pem.Block{
|
||||||
|
Type: "CERTIFICATE",
|
||||||
|
Bytes: certBytes,
|
||||||
|
}
|
||||||
|
certPem = pem.EncodeToMemory(&certPemBlock)
|
||||||
|
if err != nil {
|
||||||
|
return certPem, keyPem, err
|
||||||
|
}
|
||||||
|
return certPem, keyPem, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateX509CACert(commonName string) ([]byte, []byte, error) {
|
||||||
|
var err error
|
||||||
|
certPem := make([]byte, 0)
|
||||||
|
keyPem := make([]byte, 0)
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
const yearsAfter int = 10
|
||||||
|
const keySize int = 2048
|
||||||
|
|
||||||
|
key, err := rsa.GenerateKey(rand.Reader, keySize)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("Can't create a private key: %v", err)
|
||||||
|
return certPem, keyPem, err
|
||||||
|
|
||||||
|
}
|
||||||
|
keyPemBlock := pem.Block{
|
||||||
|
Type: "RSA PRIVATE KEY",
|
||||||
|
Bytes: x509.MarshalPKCS1PrivateKey(key),
|
||||||
|
}
|
||||||
|
keyPem = pem.EncodeToMemory(&keyPemBlock)
|
||||||
|
|
||||||
|
certSubject := pkix.Name{
|
||||||
|
CommonName: commonName,
|
||||||
|
}
|
||||||
|
certIssuer := certSubject
|
||||||
|
|
||||||
|
tml := x509.Certificate{
|
||||||
|
SerialNumber: big.NewInt(now.Unix()),
|
||||||
|
NotBefore: now,
|
||||||
|
NotAfter: now.AddDate(yearsAfter, 0, 0),
|
||||||
|
Subject: certSubject,
|
||||||
|
Issuer: certIssuer,
|
||||||
|
IsCA: true,
|
||||||
|
ExtKeyUsage: []x509.ExtKeyUsage{
|
||||||
|
x509.ExtKeyUsageClientAuth,
|
||||||
|
x509.ExtKeyUsageServerAuth},
|
||||||
|
KeyUsage: x509.KeyUsageDigitalSignature |
|
||||||
|
x509.KeyUsageCertSign |
|
||||||
|
x509.KeyUsageKeyEncipherment |
|
||||||
|
x509.KeyUsageCRLSign,
|
||||||
|
BasicConstraintsValid: true,
|
||||||
|
}
|
||||||
|
certBytes, err := x509.CreateCertificate(rand.Reader, &tml, &tml, &key.PublicKey, key)
|
||||||
|
if err != nil {
|
||||||
|
return certPem, keyPem, fmt.Errorf("Can't create a certificate: %v", err)
|
||||||
|
|
||||||
|
}
|
||||||
|
certPemBlock := pem.Block{
|
||||||
|
Type: "CERTIFICATE",
|
||||||
|
Bytes: certBytes,
|
||||||
|
}
|
||||||
|
certPem = pem.EncodeToMemory(&certPemBlock)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return certPem, keyPem, err
|
||||||
|
}
|
||||||
|
return certPem, keyPem, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package aux509
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCert(t *testing.T) {
|
||||||
|
|
||||||
|
{
|
||||||
|
//caCert, caKey, err := CreateX509SelfSignedCert("test1")
|
||||||
|
//require.NoError(t, err)
|
||||||
|
//fmt.Println(string(caCert))
|
||||||
|
//fmt.Println(string(caKey))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
caCert, caKey, err := CreateX509CACert("test1")
|
||||||
|
require.NoError(t, err)
|
||||||
|
fmt.Println(string(caCert))
|
||||||
|
fmt.Println(string(caKey))
|
||||||
|
|
||||||
|
// caCert, caKey, err = CreateX509Cert("test1", caKey)
|
||||||
|
// require.NoError(t, err)
|
||||||
|
// fmt.Println(string(caCert))
|
||||||
|
// fmt.Println(string(caKey))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package auxgin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CorsMiddleware() gin.HandlerFunc {
|
||||||
|
|
||||||
|
headers := []string{"Content-Type", "Content-Length", "Accept-Encoding", "X-CSRF-Token", "Authorization"}
|
||||||
|
headerList := strings.Join(headers, ",")
|
||||||
|
|
||||||
|
methods := []string{"POST", "GET", "OPTIONS", "PUT", "DELETE", "UPDATE"}
|
||||||
|
methodList := strings.Join(methods, ",")
|
||||||
|
|
||||||
|
return func(gctx *gin.Context) {
|
||||||
|
gctx.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
||||||
|
gctx.Writer.Header().Set("Access-Control-Max-Age", "86400")
|
||||||
|
gctx.Writer.Header().Set("Access-Control-Allow-Methods", methodList)
|
||||||
|
gctx.Writer.Header().Set("Access-Control-Allow-Headers", headerList)
|
||||||
|
gctx.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||||
|
|
||||||
|
if gctx.Request.Method == "OPTIONS" {
|
||||||
|
gctx.AbortWithStatus(http.StatusOK)
|
||||||
|
} else {
|
||||||
|
gctx.Next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package auxgin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LogMiddleware() gin.HandlerFunc {
|
||||||
|
return func(ctx *gin.Context) {
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
ctx.Next()
|
||||||
|
|
||||||
|
var reqSize int64
|
||||||
|
var method string
|
||||||
|
var reqURI string
|
||||||
|
var remAddr string
|
||||||
|
if ctx.Request != nil {
|
||||||
|
reqSize = ctx.Request.ContentLength
|
||||||
|
method = ctx.Request.Method
|
||||||
|
reqURI = ctx.Request.RequestURI
|
||||||
|
remAddr = ctx.RemoteIP()
|
||||||
|
}
|
||||||
|
|
||||||
|
duration := time.Since(start).Microseconds()
|
||||||
|
|
||||||
|
var resCode int
|
||||||
|
var resSize int
|
||||||
|
if ctx.Writer != nil {
|
||||||
|
resCode = ctx.Writer.Status()
|
||||||
|
resSize = ctx.Writer.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
logString := fmt.Sprintf("%s %s %s in=%d out=%d res=%d %dms",
|
||||||
|
remAddr, method, reqURI, reqSize, resSize, resCode, duration)
|
||||||
|
|
||||||
|
logger := logrus.WithField("object", "accesslog")
|
||||||
|
logger.Infoln(logString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type LogWriter struct {
|
||||||
|
gin.ResponseWriter
|
||||||
|
body *bytes.Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lw LogWriter) Write(data []byte) (int, error) {
|
||||||
|
lw.body.Write(data)
|
||||||
|
return lw.ResponseWriter.Write(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lw LogWriter) WriteString(data string) (int, error) {
|
||||||
|
lw.body.WriteString(data)
|
||||||
|
return lw.ResponseWriter.WriteString(data)
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package auxgin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RequestLogMiddleware() gin.HandlerFunc {
|
||||||
|
return func(context *gin.Context) {
|
||||||
|
|
||||||
|
contentType := context.GetHeader("Content-Type")
|
||||||
|
contentType = strings.ToLower(contentType)
|
||||||
|
|
||||||
|
var requestBody []byte
|
||||||
|
if context.Request.Body != nil {
|
||||||
|
requestBody, _ = ioutil.ReadAll(context.Request.Body)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(contentType, "application/json") && context.Request.Method == "POST" {
|
||||||
|
buffer := bytes.NewBuffer(nil)
|
||||||
|
json.Indent(buffer, requestBody, "", " ")
|
||||||
|
logger := logrus.WithField("object", "requestlog")
|
||||||
|
logger.Infoln("request:\n", buffer.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Request.Body = ioutil.NopCloser(bytes.NewReader(requestBody))
|
||||||
|
context.Next()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package auxgin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ResponseLogMiddleware() gin.HandlerFunc {
|
||||||
|
return func(context *gin.Context) {
|
||||||
|
contentType := context.GetHeader("Content-Type")
|
||||||
|
contentType = strings.ToLower(contentType)
|
||||||
|
|
||||||
|
writer := &LogWriter{
|
||||||
|
body: bytes.NewBuffer(nil),
|
||||||
|
ResponseWriter: context.Writer,
|
||||||
|
}
|
||||||
|
context.Writer = writer
|
||||||
|
|
||||||
|
context.Next()
|
||||||
|
|
||||||
|
if strings.Contains(contentType, "application/json") {
|
||||||
|
buffer := bytes.NewBuffer(nil)
|
||||||
|
json.Indent(buffer, writer.body.Bytes(), "", " ")
|
||||||
|
logger := logrus.WithField("object", "responselog")
|
||||||
|
logger.Infoln("request:\n", buffer.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package auxgrpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FmtError(err error) error {
|
||||||
|
if err != nil {
|
||||||
|
st, ok := status.FromError(err)
|
||||||
|
if !ok {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err := fmt.Errorf("Return code %d, %s", st.Code(), st.Message())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package auxhttp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GenericResponse[T any] struct {
|
||||||
|
Result T `json:"result,omitempty"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
Error bool `json:"error"`
|
||||||
|
ErrorCode int64 `json:"errorCode"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendError(c *gin.Context, err error) {
|
||||||
|
var response GenericResponse[interface{}]
|
||||||
|
response.Error = true
|
||||||
|
if err != nil {
|
||||||
|
response.Message = err.Error()
|
||||||
|
response.ErrorCode = 101
|
||||||
|
}
|
||||||
|
c.AbortWithStatusJSON(http.StatusOK, response)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendResult(c *gin.Context, result any) {
|
||||||
|
var response GenericResponse[any]
|
||||||
|
response.Result = result
|
||||||
|
c.JSON(http.StatusOK, response)
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package auxhttp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetBearerToken(authHeader string) (string, error) {
|
||||||
|
var err error
|
||||||
|
var res string
|
||||||
|
|
||||||
|
const bearerKey = "Bearer"
|
||||||
|
const numWords = 2
|
||||||
|
|
||||||
|
authData := strings.SplitN(authHeader, " ", numWords)
|
||||||
|
if len(authData) < numWords {
|
||||||
|
err = errors.New("Authorization key and value not found")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
authKey := strings.TrimSpace(authData[0])
|
||||||
|
if authKey != bearerKey {
|
||||||
|
err = fmt.Errorf("Authorization type is different from %s", bearerKey)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
token := authData[1]
|
||||||
|
token = strings.TrimSpace(token)
|
||||||
|
|
||||||
|
if len(token) == 0 {
|
||||||
|
return res, errors.New("Lenght of authorization token must be greater zero")
|
||||||
|
}
|
||||||
|
res = token
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func HaveBearerToken(authHeader string) bool {
|
||||||
|
const bearerKey = "Bearer"
|
||||||
|
const numWords = 2
|
||||||
|
|
||||||
|
authData := strings.SplitN(authHeader, " ", numWords)
|
||||||
|
if len(authData) < numWords {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
authKey := strings.TrimSpace(authData[0])
|
||||||
|
if authKey != bearerKey {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
token := authData[1]
|
||||||
|
token = strings.TrimSpace(token)
|
||||||
|
|
||||||
|
if len(token) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package auxhttp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ParseAuthBasicHeader(header string) (string, string, error) {
|
||||||
|
var err error
|
||||||
|
var username string
|
||||||
|
var password string
|
||||||
|
|
||||||
|
authData := strings.SplitN(header, " ", 2)
|
||||||
|
if len(authData) < 2 {
|
||||||
|
err = errors.New("Wrong authentification header")
|
||||||
|
return username, password, err
|
||||||
|
}
|
||||||
|
authType := strings.TrimSpace(authData[0])
|
||||||
|
if authType != "Basic" {
|
||||||
|
err = errors.New("Authentification type is different from basic")
|
||||||
|
return username, password, err
|
||||||
|
}
|
||||||
|
authPair := strings.TrimSpace(authData[1])
|
||||||
|
|
||||||
|
pairEncoded, err := base64.StdEncoding.DecodeString(authPair)
|
||||||
|
if err != nil {
|
||||||
|
return username, password, err
|
||||||
|
}
|
||||||
|
pair := strings.SplitN(string(pairEncoded), ":", 2)
|
||||||
|
if len(pair) < 2 {
|
||||||
|
err = errors.New("Wrong authentification pair")
|
||||||
|
return username, password, err
|
||||||
|
}
|
||||||
|
username = strings.TrimSpace(pair[0])
|
||||||
|
password = strings.TrimSpace(pair[1])
|
||||||
|
|
||||||
|
if username == "" {
|
||||||
|
err = errors.New("autentification username is null")
|
||||||
|
return username, password, err
|
||||||
|
}
|
||||||
|
if password == "" {
|
||||||
|
err = errors.New("autentification password is null")
|
||||||
|
return username, password, err
|
||||||
|
}
|
||||||
|
return username, password, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package auxid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
idMtx sync.Mutex
|
||||||
|
lastID int64
|
||||||
|
)
|
||||||
|
|
||||||
|
func GenID() int64 {
|
||||||
|
// 53 bit limit for js
|
||||||
|
// See https://stackoverflow.com/questions/1379934/large-numbers-erroneously-rounded-in-javascript
|
||||||
|
idMtx.Lock()
|
||||||
|
defer idMtx.Unlock()
|
||||||
|
for {
|
||||||
|
id := (time.Now().UnixNano() / 1000) // - 10000000000000
|
||||||
|
if id != lastID {
|
||||||
|
lastID = id
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
time.Sleep(1 * time.Microsecond)
|
||||||
|
}
|
||||||
|
//10467328383814
|
||||||
|
}
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
package auxpwd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/sha256"
|
||||||
|
"crypto/sha512"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var rnd *rand.Rand
|
||||||
|
|
||||||
|
const (
|
||||||
|
sha256Prefix = "sha256pwd"
|
||||||
|
sha512Prefix = "sha512pwd"
|
||||||
|
saltSize = 16
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
src := rand.NewSource(time.Now().UnixNano())
|
||||||
|
rnd = rand.New(src)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeSHA256Hash(passwd []byte) string {
|
||||||
|
var res string
|
||||||
|
salt := hex.EncodeToString(randomBytes(saltSize))
|
||||||
|
passwdString := hex.EncodeToString(passwd)
|
||||||
|
passwdString = fmt.Sprintf("%s%s", passwdString, salt)
|
||||||
|
|
||||||
|
hasher := sha256.New()
|
||||||
|
hasher.Write([]byte(passwdString))
|
||||||
|
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||||
|
|
||||||
|
res = fmt.Sprintf("%s:%s:%s", sha256Prefix, salt, checksum)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeSHA512Hash(passwd []byte) string {
|
||||||
|
var res string
|
||||||
|
salt := hex.EncodeToString(randomBytes(saltSize))
|
||||||
|
passwdString := hex.EncodeToString(passwd)
|
||||||
|
passwdString = fmt.Sprintf("%s%s", passwdString, salt)
|
||||||
|
|
||||||
|
hasher := sha512.New()
|
||||||
|
hasher.Write([]byte(passwdString))
|
||||||
|
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||||
|
|
||||||
|
res = fmt.Sprintf("%s:%s:%s", sha512Prefix, salt, checksum)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func PasswordMatchCompat(passwd []byte, hash string) bool {
|
||||||
|
if !strings.HasPrefix(hash, sha256Prefix) && !strings.HasPrefix(hash, sha512Prefix) {
|
||||||
|
if bytes.Equal(passwd, []byte(hash)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
hashComponents := strings.Split(hash, ":")
|
||||||
|
if len(hashComponents) != 3 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
method := hashComponents[0]
|
||||||
|
salt := hashComponents[1]
|
||||||
|
controlChecksum := hashComponents[2]
|
||||||
|
|
||||||
|
switch method {
|
||||||
|
case sha256Prefix:
|
||||||
|
passwdString := hex.EncodeToString(passwd)
|
||||||
|
passwdString = fmt.Sprintf("%s%s", passwdString, salt)
|
||||||
|
hasher := sha256.New()
|
||||||
|
hasher.Write([]byte(passwdString))
|
||||||
|
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||||
|
if checksum != controlChecksum {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case sha512Prefix:
|
||||||
|
passwdString := hex.EncodeToString(passwd)
|
||||||
|
passwdString = fmt.Sprintf("%s%s", passwdString, salt)
|
||||||
|
hasher := sha512.New()
|
||||||
|
hasher.Write([]byte(passwdString))
|
||||||
|
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||||
|
if checksum != controlChecksum {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func randomString(n int) string {
|
||||||
|
const letters = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
arr := make([]byte, n)
|
||||||
|
lettersArrayLen := len(letters)
|
||||||
|
for i := range arr {
|
||||||
|
arr[i] = letters[rnd.Intn(lettersArrayLen)]
|
||||||
|
}
|
||||||
|
return string(arr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func randomBytes(n int) []byte {
|
||||||
|
arr := make([]byte, n)
|
||||||
|
for i := range arr {
|
||||||
|
arr[i] = byte(rnd.Intn(256) & 0xFF)
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package auxpwd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPasswd256(t *testing.T) {
|
||||||
|
password := []byte("123456781")
|
||||||
|
wrongPasswd := []byte("qwerty")
|
||||||
|
|
||||||
|
hash := MakeSHA256Hash(password)
|
||||||
|
fmt.Printf("%s\n", hash)
|
||||||
|
{
|
||||||
|
match := PasswordMatchCompat(password, hash)
|
||||||
|
require.Equal(t, true, match)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
match := PasswordMatchCompat(wrongPasswd, hash)
|
||||||
|
require.NotEqual(t, true, match)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPasswd512(t *testing.T) {
|
||||||
|
password := []byte("123456781")
|
||||||
|
wrongPasswd := []byte("qwerty")
|
||||||
|
|
||||||
|
hash := MakeSHA512Hash(password)
|
||||||
|
fmt.Printf("%s\n", hash)
|
||||||
|
{
|
||||||
|
match := PasswordMatchCompat(password, hash)
|
||||||
|
require.Equal(t, true, match)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
match := PasswordMatchCompat(wrongPasswd, hash)
|
||||||
|
require.NotEqual(t, true, match)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||||
|
*/
|
||||||
|
package auxtool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Clean only overbase elements of dir path if possible
|
||||||
|
func CleanDirs(basedir, datadir string) {
|
||||||
|
separator := string(os.PathSeparator)
|
||||||
|
|
||||||
|
basedir = filepath.Clean(separator + basedir)
|
||||||
|
datadir = filepath.Clean(separator + datadir)
|
||||||
|
|
||||||
|
items := strings.Split(datadir, separator)
|
||||||
|
for i := len(items); i > 0; i-- {
|
||||||
|
p := filepath.Join(items[0:i]...)
|
||||||
|
p = filepath.Clean(separator + p)
|
||||||
|
if p == basedir {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
fileInfo, err := os.Stat(p)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if fileInfo.IsDir() {
|
||||||
|
err = os.Remove(p)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package auxtool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FileExists(name string) bool {
|
||||||
|
fileStat, err := os.Stat(name)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if fileStat.IsDir() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func DirExists(name string) bool {
|
||||||
|
fileStat, err := os.Stat(name)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if fileStat == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return fileStat.IsDir()
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package auxtool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RandomString(n int) string {
|
||||||
|
const letters = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
arr := make([]byte, n)
|
||||||
|
for i := range arr {
|
||||||
|
arr[i] = letters[rand.Intn(len(letters))]
|
||||||
|
}
|
||||||
|
return string(arr)
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||||
|
*/
|
||||||
|
package auxtool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeTmpFilename(prefix string) string {
|
||||||
|
randBytes := make([]byte, 6)
|
||||||
|
rand.Read(randBytes)
|
||||||
|
suffix := hex.EncodeToString(randBytes)
|
||||||
|
return fmt.Sprintf("%s.tmp.%s", prefix, suffix)
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||||
|
*/
|
||||||
|
package auxtool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TimeNow() string {
|
||||||
|
return time.Now().Format(time.RFC3339)
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AuthCredential struct {
|
||||||
|
Payload map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAuthCredential(username, password string) *AuthCredential {
|
||||||
|
payload := make(map[string]string)
|
||||||
|
payload["username"] = username
|
||||||
|
payload["password"] = password
|
||||||
|
return &AuthCredential{
|
||||||
|
Payload: payload,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cred *AuthCredential) GetRequestMetadata(ctx context.Context, data ...string) (map[string]string, error) {
|
||||||
|
var err error
|
||||||
|
return cred.Payload, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cred *AuthCredential) RequireTransportSecurity() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/credentials"
|
||||||
|
|
||||||
|
"mbase/pkg/mbctl"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DefaultPort uint32 = 1027
|
||||||
|
)
|
||||||
|
|
||||||
|
type Access struct {
|
||||||
|
Hostname string
|
||||||
|
Port uint32
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewClient(access *Access) (*grpc.ClientConn, mbctl.ControlClient, error) {
|
||||||
|
var err error
|
||||||
|
var cli mbctl.ControlClient
|
||||||
|
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
}
|
||||||
|
const dialTimeout time.Duration = 10 * time.Second
|
||||||
|
const idleTimeout time.Duration = 30 * time.Second
|
||||||
|
|
||||||
|
authCred := NewAuthCredential(access.Username, access.Password)
|
||||||
|
dialOpts := []grpc.DialOption{
|
||||||
|
grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)),
|
||||||
|
grpc.WithPerRPCCredentials(authCred),
|
||||||
|
grpc.WithBlock(),
|
||||||
|
grpc.WithIdleTimeout(idleTimeout),
|
||||||
|
}
|
||||||
|
address := fmt.Sprintf("%s:%d", access.Hostname, access.Port)
|
||||||
|
ctx, _ := context.WithTimeout(context.Background(), dialTimeout)
|
||||||
|
conn, err := grpc.DialContext(ctx, address, dialOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return conn, cli, fmt.Errorf("Dial error: %v", err)
|
||||||
|
}
|
||||||
|
cli = mbctl.NewControlClient(conn)
|
||||||
|
return conn, cli, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
package cm509
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func EncryptAES256(b64data string, key string) (string, error) {
|
||||||
|
var res string
|
||||||
|
var err error
|
||||||
|
|
||||||
|
const aes256KeyLen = 32
|
||||||
|
|
||||||
|
bKey := []byte(key)
|
||||||
|
keyLen := len(bKey)
|
||||||
|
switch {
|
||||||
|
case keyLen > aes256KeyLen:
|
||||||
|
bKey = bKey[:aes256KeyLen]
|
||||||
|
case keyLen < aes256KeyLen:
|
||||||
|
padding := make([]byte, aes256KeyLen-keyLen)
|
||||||
|
bKey = append(bKey, padding...)
|
||||||
|
case keyLen == 0:
|
||||||
|
return res, fmt.Errorf("Zero lenght key")
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := base64.StdEncoding.DecodeString(b64data)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
block, err := aes.NewCipher(bKey)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nonce := make([]byte, 12)
|
||||||
|
_, err = io.ReadFull(rand.Reader, nonce)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
aesgcm, err := cipher.NewGCM(block)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ciphertext := aesgcm.Seal(nil, nonce, data, nil)
|
||||||
|
ciphertext = append(nonce, ciphertext...)
|
||||||
|
|
||||||
|
res = base64.StdEncoding.EncodeToString(ciphertext)
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func DecryptAES256(b64ciphertext string, key string) (string, error) {
|
||||||
|
var res string
|
||||||
|
var err error
|
||||||
|
|
||||||
|
const aes256KeyLen = 32
|
||||||
|
|
||||||
|
bKey := []byte(key)
|
||||||
|
keyLen := len(bKey)
|
||||||
|
switch {
|
||||||
|
case keyLen > aes256KeyLen:
|
||||||
|
bKey = bKey[:aes256KeyLen]
|
||||||
|
case keyLen < aes256KeyLen:
|
||||||
|
padding := make([]byte, aes256KeyLen-keyLen)
|
||||||
|
bKey = append(bKey, padding...)
|
||||||
|
case keyLen == 0:
|
||||||
|
return res, fmt.Errorf("Zero lenght key")
|
||||||
|
}
|
||||||
|
|
||||||
|
ciphertext, err := base64.StdEncoding.DecodeString(b64ciphertext)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
block, err := aes.NewCipher(bKey)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
aesgcm, err := cipher.NewGCM(block)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nonceSize := aesgcm.NonceSize()
|
||||||
|
nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
|
||||||
|
|
||||||
|
plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res = base64.StdEncoding.EncodeToString(plaintext)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package cm509
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAES(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
src := "1234567890123456789012345678901234567890"
|
||||||
|
b64src := base64.StdEncoding.EncodeToString([]byte(src))
|
||||||
|
key := "12345678901234"
|
||||||
|
encSrc, err := EncryptAES256(b64src, key)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotZero(t, len(encSrc))
|
||||||
|
|
||||||
|
decSrc, err := DecryptAES256(encSrc, key)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotZero(t, len(decSrc))
|
||||||
|
require.Equal(t, b64src, decSrc)
|
||||||
|
|
||||||
|
dst, err := base64.StdEncoding.DecodeString(decSrc)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, len(src), len(dst))
|
||||||
|
require.Equal(t, string(src), string(dst))
|
||||||
|
|
||||||
|
fmt.Printf("%s\n", src)
|
||||||
|
fmt.Printf("%s\n", dst)
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIHZDCCBkygAwIBAgISA0TPqlhFqMMjfL8lwr1WdKCiMA0GCSqGSIb3DQEBCwUA
|
||||||
|
MDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQwwCgYDVQQD
|
||||||
|
EwNSMTEwHhcNMjQwNzE1MDcwNTQyWhcNMjQxMDEzMDcwNTQxWjAYMRYwFAYDVQQD
|
||||||
|
Ew1oYW0udW5peDcub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
||||||
|
xDw3k4983QmRIqV0PsXFfG3x1wkamrMrY9sMz+M+CR9h1iozv4OQdm5wFJp/8ert
|
||||||
|
7x+JS07v4vabYoLyVsdteRXHrqXlSDJMuZaReHIQVqKk1BYZ9miIH64ExUA6vd3r
|
||||||
|
8AmilipIPW+UJihaZnP7wPy80PUdCiq0tnSewKN+wfzka5yehWXeaTbDeDoUl1Cf
|
||||||
|
5Q3CO9KhbIYNwG8GBm+4YKiuewjjIU4sPEaCPvpvCTcwA4Lcqf1awU/nRdTLXO1e
|
||||||
|
L4LezTEPb7KSS7hEZSHs2aQbjVpoV0IcuSYI1beb7XSdsv/jDIzOpu/Sx+AqMUy+
|
||||||
|
WE4sO0Yj3ap8mbsY9HTC7QIDAQABo4IEizCCBIcwDgYDVR0PAQH/BAQDAgWgMB0G
|
||||||
|
A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1Ud
|
||||||
|
DgQWBBR3smydoErE3KVUBr0/ohKZ0ghK0jAfBgNVHSMEGDAWgBTFz0ak6vTDwHps
|
||||||
|
lcQtsF6SLybjuTBXBggrBgEFBQcBAQRLMEkwIgYIKwYBBQUHMAGGFmh0dHA6Ly9y
|
||||||
|
MTEuby5sZW5jci5vcmcwIwYIKwYBBQUHMAKGF2h0dHA6Ly9yMTEuaS5sZW5jci5v
|
||||||
|
cmcvMIICkAYDVR0RBIIChzCCAoOCEmFpcmZvcmNlLnVuaXg3Lm9yZ4IOYXJ0cy51
|
||||||
|
bml4Ny5vcmeCDWRlNC51bml4Ny5vcmeCDWRlNS51bml4Ny5vcmeCDWRlNi51bml4
|
||||||
|
Ny5vcmeCDWRlNy51bml4Ny5vcmeCDWRlYi51bml4Ny5vcmeCDWRldi51bml4Ny5v
|
||||||
|
cmeCDmRuczUudW5peDcub3Jngg1lZHUudW5peDcub3JnghBlZHVtYXgudW5peDcu
|
||||||
|
b3Jngg1naXQudW5peDcub3Jngg9nbWFpbC51bml4Ny5vcmeCDWhhbS51bml4Ny5v
|
||||||
|
cmeCDmhhc2gudW5peDcub3JnggxoZC51bml4Ny5vcmeCDmhlYXAudW5peDcub3Jn
|
||||||
|
ghJob21lZGVzay51bml4Ny5vcmeCDWh1Yi51bml4Ny5vcmeCEGl0ZGVzay51bml4
|
||||||
|
Ny5vcmeCD2xhcGlzLnVuaXg3Lm9yZ4IPbG9yZW0udW5peDcub3Jngg5tYWlsLnVu
|
||||||
|
aXg3Lm9yZ4IMbXcudW5peDcub3JnggxteC51bml4Ny5vcmeCDnBkbnMudW5peDcu
|
||||||
|
b3Jngg5waWtpLnVuaXg3Lm9yZ4IPcHJveHkudW5peDcub3JnghFyZWRtaW5lLnVu
|
||||||
|
aXg3Lm9yZ4IMcm0udW5peDcub3Jngg9zbGFjay51bml4Ny5vcmeCEHNwcmluZy51
|
||||||
|
bml4Ny5vcmeCDnNydjcudW5peDcub3JnghBzdG9yZXgudW5peDcub3JnghB0YW5h
|
||||||
|
a2gudW5peDcub3Jnggx2NS51bml4Ny5vcmeCDXcxMi51bml4Ny5vcmeCDXdjbS51
|
||||||
|
bml4Ny5vcmeCDndpa2kudW5peDcub3Jngg13d3cudW5peDcub3JnMBMGA1UdIAQM
|
||||||
|
MAowCAYGZ4EMAQIBMIIBBAYKKwYBBAHWeQIEAgSB9QSB8gDwAHcASLDja9qmRzQP
|
||||||
|
5WoC+p0w6xxSActW3SyB2bu/qznYhHMAAAGQtW0RVQAABAMASDBGAiEAjQvvzpOR
|
||||||
|
urMOiqV5g0EuAK1A9CuAKOdWJp6/s3/SKBMCIQCbTBj13lhMnTr6bSHwoBtSwoiY
|
||||||
|
aeDJzGBmDTpbgGpFdQB1AN/hVuuqBa+1nA+GcY2owDJOrlbZbqf1pWoB0cE7vlJc
|
||||||
|
AAABkLVtEicAAAQDAEYwRAIgWe0pdXXB6UmMmeSgYLDncdkS2aKHAHDdOqKOoL9x
|
||||||
|
Kx8CIBqobR/Ve1IZMTLrRN54vh8kNmF0OkVjXtrh+ste6cKUMA0GCSqGSIb3DQEB
|
||||||
|
CwUAA4IBAQA3c88cXIejS9vy4XUow6dOuud6qqkNX1osSq2vRtYkKMZb2JVuhPAr
|
||||||
|
hQsozwptJPm5lOEDQPD8676yZNVgGdjmMvA0ewdWEp9HZ7x+RFlI7RC9CqMSOWPO
|
||||||
|
p60RMiBQlK7Els38WurmW2GzZkfykzpZZ/0lIrCNjT7aB9VjGVDOjxo/xHapHSwJ
|
||||||
|
GOxq4TTU1KaFfbFl5A2F9bRVrAAWfih+DzUzhlhZBHODzadgs2CimVYIp8gEVf1j
|
||||||
|
dGetiU2j+cvOpvQnfX7Xr8Cf2YK7E0j6lfC3RPvK9oA1bP5KBMWELXsGBrwIxgUB
|
||||||
|
f2/jRcxrQoGoEYwYW4D/JViKwelABzfc
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFBjCCAu6gAwIBAgIRAIp9PhPWLzDvI4a9KQdrNPgwDQYJKoZIhvcNAQELBQAw
|
||||||
|
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||||
|
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw
|
||||||
|
WhcNMjcwMzEyMjM1OTU5WjAzMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
|
||||||
|
RW5jcnlwdDEMMAoGA1UEAxMDUjExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||||
|
CgKCAQEAuoe8XBsAOcvKCs3UZxD5ATylTqVhyybKUvsVAbe5KPUoHu0nsyQYOWcJ
|
||||||
|
DAjs4DqwO3cOvfPlOVRBDE6uQdaZdN5R2+97/1i9qLcT9t4x1fJyyXJqC4N0lZxG
|
||||||
|
AGQUmfOx2SLZzaiSqhwmej/+71gFewiVgdtxD4774zEJuwm+UE1fj5F2PVqdnoPy
|
||||||
|
6cRms+EGZkNIGIBloDcYmpuEMpexsr3E+BUAnSeI++JjF5ZsmydnS8TbKF5pwnnw
|
||||||
|
SVzgJFDhxLyhBax7QG0AtMJBP6dYuC/FXJuluwme8f7rsIU5/agK70XEeOtlKsLP
|
||||||
|
Xzze41xNG/cLJyuqC0J3U095ah2H2QIDAQABo4H4MIH1MA4GA1UdDwEB/wQEAwIB
|
||||||
|
hjAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwEgYDVR0TAQH/BAgwBgEB
|
||||||
|
/wIBADAdBgNVHQ4EFgQUxc9GpOr0w8B6bJXELbBeki8m47kwHwYDVR0jBBgwFoAU
|
||||||
|
ebRZ5nu25eQBc4AIiMgaWPbpm24wMgYIKwYBBQUHAQEEJjAkMCIGCCsGAQUFBzAC
|
||||||
|
hhZodHRwOi8veDEuaS5sZW5jci5vcmcvMBMGA1UdIAQMMAowCAYGZ4EMAQIBMCcG
|
||||||
|
A1UdHwQgMB4wHKAaoBiGFmh0dHA6Ly94MS5jLmxlbmNyLm9yZy8wDQYJKoZIhvcN
|
||||||
|
AQELBQADggIBAE7iiV0KAxyQOND1H/lxXPjDj7I3iHpvsCUf7b632IYGjukJhM1y
|
||||||
|
v4Hz/MrPU0jtvfZpQtSlET41yBOykh0FX+ou1Nj4ScOt9ZmWnO8m2OG0JAtIIE38
|
||||||
|
01S0qcYhyOE2G/93ZCkXufBL713qzXnQv5C/viOykNpKqUgxdKlEC+Hi9i2DcaR1
|
||||||
|
e9KUwQUZRhy5j/PEdEglKg3l9dtD4tuTm7kZtB8v32oOjzHTYw+7KdzdZiw/sBtn
|
||||||
|
UfhBPORNuay4pJxmY/WrhSMdzFO2q3Gu3MUBcdo27goYKjL9CTF8j/Zz55yctUoV
|
||||||
|
aneCWs/ajUX+HypkBTA+c8LGDLnWO2NKq0YD/pnARkAnYGPfUDoHR9gVSp/qRx+Z
|
||||||
|
WghiDLZsMwhN1zjtSC0uBWiugF3vTNzYIEFfaPG7Ws3jDrAMMYebQ95JQ+HIBD/R
|
||||||
|
PBuHRTBpqKlyDnkSHDHYPiNX3adPoPAcgdF3H2/W0rmoswMWgTlLn1Wu0mrks7/q
|
||||||
|
pdWfS6PJ1jty80r2VKsM/Dj3YIDfbjXKdaFU5C+8bhfJGqU3taKauuz0wHVGT3eo
|
||||||
|
6FlWkWYtbt4pgdamlwVeZEW+LM7qZEJEsMNPrfC03APKmZsJgpWCDWOKZvkZcvjV
|
||||||
|
uYkQ4omYCTX5ohy+knMjdOmdH9c7SpqEWBDC86fiNex+O0XOMEZSa8DA
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/
|
||||||
|
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
|
||||||
|
DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow
|
||||||
|
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||||
|
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB
|
||||||
|
AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC
|
||||||
|
ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL
|
||||||
|
wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D
|
||||||
|
LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK
|
||||||
|
4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5
|
||||||
|
bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y
|
||||||
|
sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ
|
||||||
|
Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4
|
||||||
|
FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc
|
||||||
|
SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql
|
||||||
|
PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND
|
||||||
|
TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
|
||||||
|
SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1
|
||||||
|
c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx
|
||||||
|
+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB
|
||||||
|
ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu
|
||||||
|
b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E
|
||||||
|
U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu
|
||||||
|
MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC
|
||||||
|
5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW
|
||||||
|
9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG
|
||||||
|
WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O
|
||||||
|
he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC
|
||||||
|
Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFVDCCBDygAwIBAgIRAKLBiJX85huxZJB/Ylc2Y5gwDQYJKoZIhvcNAQEFBQAw
|
||||||
|
gakxCzAJBgNVBAYTAnVzMQ0wCwYDVQQIEwRVdGFoMRcwFQYDVQQHEw5TYWx0IExh
|
||||||
|
a2UgQ2l0eTEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREw
|
||||||
|
DwYDVQQLEwhEU1RDQSBYMTEWMBQGA1UEAxMNRFNUIFJvb3RDQSBYMTEhMB8GCSqG
|
||||||
|
SIb3DQEJARYSY2FAZGlnc2lndHJ1c3QuY29tMB4XDTA0MDkwODE0NDM0NVoXDTA4
|
||||||
|
MTEyODEzMDI1OVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3Qg
|
||||||
|
Q28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
|
||||||
|
ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+Do
|
||||||
|
M3ZJKuM/IUmTrE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwG
|
||||||
|
MoOifooUMM0RoOEqOLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOe
|
||||||
|
DNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqc
|
||||||
|
kh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr
|
||||||
|
2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaOCAd4wggHaMA8GA1Ud
|
||||||
|
EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMIG7BgNVHR8EgbMwgbAwga2ggaqg
|
||||||
|
gaeGgaRsZGFwOi8vbGRhcC5kaWdzaWd0cnVzdC5jb20vY249RFNUJTIwUm9vdENB
|
||||||
|
JTIwWDEsb3U9RFNUQ0ElMjBYMSxvPURpZ2l0YWwlMjBTaWduYXR1cmUlMjBUcnVz
|
||||||
|
dCUyMENvLixsPVNhbHQlMjBMYWtlJTIwQ2l0eSxTPVV0YWgsYz11cz9jZXJ0aWZp
|
||||||
|
Y2F0ZVJldm9jYXRpb25MaXN0O2JpbmFyeTCBuAYIKwYBBQUHAQEEgaswgagwgaUG
|
||||||
|
CCsGAQUFBzAChoGYbGRhcDovL2xkYXAuZGlnc2lndHJ1c3QuY29tL2NuPURTVCUy
|
||||||
|
MFJvb3RDQSUyMFgxLG91PURTVENBJTIwWDEsbz1EaWdpdGFsJTIwU2lnbmF0dXJl
|
||||||
|
JTIwVHJ1c3QlMjBDby4sbD1TYWx0JTIwTGFrZSUyMENpdHksUz1VdGFoLGM9dXM/
|
||||||
|
Y0FDZXJ0aWZpY2F0ZTtiaW5hcnkwHwYDVR0jBBgwFoAUaU2asPSCd8A2GzVVCRQa
|
||||||
|
/goSAAowHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqGSIb3DQEB
|
||||||
|
BQUAA4IBAQCpFXMtsChLFvN/Z+mwiodooamIW0qjMoVGHeN9CcDdUIGQI7cgbT10
|
||||||
|
tsJuEZx3opp2s4LoM7Gn/o0T/rysLlT34vPwI4Ei/df3aG0ite5ehqWgMuc65n1P
|
||||||
|
tadwl5JFFx3l8B0YWrOv5xJ0kY+br4FGI2OGqxagBtH2y7Uak4Iq2xipTHhlvx6a
|
||||||
|
DWAzGQHovRdLf1c4cFti11gU29QYPgDXsJSuriq3xcItGzjYZT9V45WiIlmdvez0
|
||||||
|
vCr6wcnjifctVfQ7z2o2+yl7A1+ijNhDhyfcrdPqctwx0Nk8IDitss+vNMsqoEHx
|
||||||
|
uBoIoQw0DQhKAEYri9bw+9wqZhotOjMw
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -0,0 +1,480 @@
|
|||||||
|
package cm509
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/pem"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DoubleEncodedCertKeyMatch(cert, key string) error {
|
||||||
|
var err error
|
||||||
|
certPEM, err := base64.StdEncoding.DecodeString(cert)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
keyPEM, err := base64.StdEncoding.DecodeString(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = tls.X509KeyPair(certPEM, keyPEM)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateIssuerPairParams struct {
|
||||||
|
OrganizationName string
|
||||||
|
OrganizationalUnitName string
|
||||||
|
CommonName string
|
||||||
|
SignerCert string
|
||||||
|
SignerKey string
|
||||||
|
SerialNumber int64
|
||||||
|
}
|
||||||
|
type CreateIssuerPairResult struct {
|
||||||
|
Name string
|
||||||
|
Cert string
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateIssuerPair(params *CreateIssuerPairParams) (*CreateIssuerPairResult, error) {
|
||||||
|
var err error
|
||||||
|
res := &CreateIssuerPairResult{}
|
||||||
|
|
||||||
|
if params.SignerKey != "" && params.SignerCert == "" {
|
||||||
|
err = fmt.Errorf("The signature key and certificate must be defined together")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if params.SignerKey == "" && params.SignerCert != "" {
|
||||||
|
err = fmt.Errorf("The signature key and certificate must be defined together")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var signerKey any
|
||||||
|
if params.SignerKey != "" {
|
||||||
|
signerKey, err = ParseDoubleEncodedKey(params.SignerKey)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var signerCert *x509.Certificate
|
||||||
|
if params.SignerCert != "" {
|
||||||
|
signerCert, err = ParseDoubleEncodedCerificate(params.SignerCert)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
certPem := make([]byte, 0)
|
||||||
|
keyPem := make([]byte, 0)
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
const yearsAfter int = 10
|
||||||
|
const keySize int = 2048
|
||||||
|
|
||||||
|
certKey, err := rsa.GenerateKey(rand.Reader, keySize)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("Can't create a private key: %v", err)
|
||||||
|
return res, err
|
||||||
|
|
||||||
|
}
|
||||||
|
keyPemBlock := &pem.Block{
|
||||||
|
Type: "RSA PRIVATE KEY",
|
||||||
|
Bytes: x509.MarshalPKCS1PrivateKey(certKey),
|
||||||
|
}
|
||||||
|
keyPem = pem.EncodeToMemory(keyPemBlock)
|
||||||
|
|
||||||
|
certSubject := pkix.Name{
|
||||||
|
CommonName: params.CommonName,
|
||||||
|
}
|
||||||
|
if params.OrganizationName != "" {
|
||||||
|
certSubject.Organization = []string{params.OrganizationName}
|
||||||
|
}
|
||||||
|
if params.OrganizationalUnitName != "" {
|
||||||
|
certSubject.OrganizationalUnit = []string{params.OrganizationalUnitName}
|
||||||
|
}
|
||||||
|
|
||||||
|
certIssuer := certSubject
|
||||||
|
if signerCert != nil {
|
||||||
|
certIssuer = signerCert.Subject
|
||||||
|
}
|
||||||
|
|
||||||
|
var issuerKey any = certKey
|
||||||
|
if signerKey != nil {
|
||||||
|
issuerKey = signerKey
|
||||||
|
}
|
||||||
|
|
||||||
|
res.Name = certSubject.String()
|
||||||
|
|
||||||
|
serialNumber := big.NewInt(now.UnixNano())
|
||||||
|
if params.SerialNumber != 0 {
|
||||||
|
serialNumber = big.NewInt(params.SerialNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
certTempl := &x509.Certificate{
|
||||||
|
SerialNumber: serialNumber,
|
||||||
|
NotBefore: now,
|
||||||
|
NotAfter: now.AddDate(yearsAfter, 0, 0),
|
||||||
|
Subject: certSubject,
|
||||||
|
Issuer: certIssuer,
|
||||||
|
IsCA: true,
|
||||||
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
|
||||||
|
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign |
|
||||||
|
x509.KeyUsageKeyEncipherment | x509.KeyUsageCRLSign,
|
||||||
|
BasicConstraintsValid: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
parentCert := certTempl
|
||||||
|
if signerCert != nil {
|
||||||
|
parentCert = signerCert
|
||||||
|
}
|
||||||
|
|
||||||
|
certBytes, err := x509.CreateCertificate(rand.Reader, certTempl, parentCert, &certKey.PublicKey, issuerKey)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("Can't create a certificate: %v", err)
|
||||||
|
return res, err
|
||||||
|
|
||||||
|
}
|
||||||
|
certPemBlock := pem.Block{
|
||||||
|
Type: "CERTIFICATE",
|
||||||
|
Bytes: certBytes,
|
||||||
|
}
|
||||||
|
certPem = pem.EncodeToMemory(&certPemBlock)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res.Cert = base64.StdEncoding.EncodeToString(certPem)
|
||||||
|
res.Key = base64.StdEncoding.EncodeToString(keyPem)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateServicePairParams struct {
|
||||||
|
OrganizationName string
|
||||||
|
OrganizationalUnitName string
|
||||||
|
CommonName string
|
||||||
|
DNSNames []string
|
||||||
|
IPAddresses []string
|
||||||
|
IssuerKey string
|
||||||
|
IssuerCert string
|
||||||
|
SerialNumber int64
|
||||||
|
}
|
||||||
|
type CreateServicePairResult struct {
|
||||||
|
Name string
|
||||||
|
Cert string
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateServicePair(params *CreateServicePairParams) (*CreateServicePairResult, error) {
|
||||||
|
var err error
|
||||||
|
res := &CreateServicePairResult{}
|
||||||
|
|
||||||
|
if params.IssuerKey != "" && params.IssuerCert == "" {
|
||||||
|
err = fmt.Errorf("The signature key and certificate must be defined together")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if params.IssuerKey == "" && params.IssuerCert != "" {
|
||||||
|
err = fmt.Errorf("The signature key and certificate must be defined together")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var signerKey any
|
||||||
|
if params.IssuerKey != "" {
|
||||||
|
signerKey, err = ParseDoubleEncodedKey(params.IssuerKey)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var signerCert *x509.Certificate
|
||||||
|
if params.IssuerCert != "" {
|
||||||
|
signerCert, err = ParseDoubleEncodedCerificate(params.IssuerCert)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
certPem := make([]byte, 0)
|
||||||
|
keyPem := make([]byte, 0)
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
const yearsAfter int = 10
|
||||||
|
const keySize int = 2048
|
||||||
|
|
||||||
|
certKey, err := rsa.GenerateKey(rand.Reader, keySize)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("Can't create a private key: %v", err)
|
||||||
|
return res, err
|
||||||
|
|
||||||
|
}
|
||||||
|
keyPemBlock := &pem.Block{
|
||||||
|
Type: "RSA PRIVATE KEY",
|
||||||
|
Bytes: x509.MarshalPKCS1PrivateKey(certKey),
|
||||||
|
}
|
||||||
|
keyPem = pem.EncodeToMemory(keyPemBlock)
|
||||||
|
|
||||||
|
certSubject := pkix.Name{
|
||||||
|
CommonName: params.CommonName,
|
||||||
|
}
|
||||||
|
if params.OrganizationName != "" {
|
||||||
|
certSubject.Organization = []string{params.OrganizationName}
|
||||||
|
}
|
||||||
|
if params.OrganizationalUnitName != "" {
|
||||||
|
certSubject.OrganizationalUnit = []string{params.OrganizationalUnitName}
|
||||||
|
}
|
||||||
|
|
||||||
|
certIssuer := certSubject
|
||||||
|
if signerCert != nil {
|
||||||
|
certIssuer = signerCert.Subject
|
||||||
|
}
|
||||||
|
|
||||||
|
var issuerKey any = certKey
|
||||||
|
if signerKey != nil {
|
||||||
|
issuerKey = signerKey
|
||||||
|
}
|
||||||
|
|
||||||
|
res.Name = certSubject.String()
|
||||||
|
|
||||||
|
var netAddresses []net.IP
|
||||||
|
if params.IPAddresses != nil && len(params.IPAddresses) > 0 {
|
||||||
|
netAddresses = make([]net.IP, 0)
|
||||||
|
for _, ipAddress := range params.IPAddresses {
|
||||||
|
netAddress := net.ParseIP(ipAddress)
|
||||||
|
netAddresses = append(netAddresses, netAddress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var dnsNames []string
|
||||||
|
if params.DNSNames != nil && len(params.DNSNames) > 0 {
|
||||||
|
dnsNames = make([]string, 0)
|
||||||
|
dnsNames = append(dnsNames, params.DNSNames...)
|
||||||
|
}
|
||||||
|
|
||||||
|
serialNumber := big.NewInt(now.UnixNano())
|
||||||
|
if params.SerialNumber != 0 {
|
||||||
|
serialNumber = big.NewInt(params.SerialNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
certTempl := &x509.Certificate{
|
||||||
|
SerialNumber: serialNumber,
|
||||||
|
NotBefore: now,
|
||||||
|
NotAfter: now.AddDate(yearsAfter, 0, 0),
|
||||||
|
Subject: certSubject,
|
||||||
|
Issuer: certIssuer,
|
||||||
|
DNSNames: dnsNames,
|
||||||
|
IPAddresses: netAddresses,
|
||||||
|
IsCA: false,
|
||||||
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
|
||||||
|
KeyUsage: x509.KeyUsageDigitalSignature,
|
||||||
|
BasicConstraintsValid: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
parentCert := certTempl
|
||||||
|
if signerCert != nil {
|
||||||
|
parentCert = signerCert
|
||||||
|
}
|
||||||
|
|
||||||
|
certBytes, err := x509.CreateCertificate(rand.Reader, certTempl, parentCert, &certKey.PublicKey, issuerKey)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("Can't create a certificate: %v", err)
|
||||||
|
return res, err
|
||||||
|
|
||||||
|
}
|
||||||
|
certPemBlock := pem.Block{
|
||||||
|
Type: "CERTIFICATE",
|
||||||
|
Bytes: certBytes,
|
||||||
|
}
|
||||||
|
certPem = pem.EncodeToMemory(&certPemBlock)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res.Cert = base64.StdEncoding.EncodeToString(certPem)
|
||||||
|
res.Key = base64.StdEncoding.EncodeToString(keyPem)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseDoubleEncodedCerificate(certString string) (*x509.Certificate, error) {
|
||||||
|
var err error
|
||||||
|
res := &x509.Certificate{}
|
||||||
|
|
||||||
|
certPEM, err := base64.StdEncoding.DecodeString(certString)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("Failed to parse base64 certificate string: %v", err)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
certBlock, _ := pem.Decode([]byte(certPEM))
|
||||||
|
if certBlock == nil {
|
||||||
|
err := fmt.Errorf("Failed to parse certificate PEM")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if certBlock.Type != "CERTIFICATE" {
|
||||||
|
err := fmt.Errorf("Unknown PEM certificate type: %s", certBlock.Type)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if len(certBlock.Bytes) == 0 {
|
||||||
|
err := fmt.Errorf("Empty PEM certificate block")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err = x509.ParseCertificate(certBlock.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseEncodedCerificate(certPEM string) (*x509.Certificate, error) {
|
||||||
|
var err error
|
||||||
|
res := &x509.Certificate{}
|
||||||
|
|
||||||
|
certBlock, _ := pem.Decode([]byte(certPEM))
|
||||||
|
if certBlock == nil {
|
||||||
|
err := fmt.Errorf("Failed to parse certificate PEM")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if certBlock.Type != "CERTIFICATE" {
|
||||||
|
err := fmt.Errorf("Unknown PEM certificate type: %s", certBlock.Type)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if len(certBlock.Bytes) == 0 {
|
||||||
|
err := fmt.Errorf("Empty PEM certificate block")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
res, err = x509.ParseCertificate(certBlock.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseDoubleEncodedKey(keyString string) (any, error) {
|
||||||
|
var err error
|
||||||
|
var res any
|
||||||
|
|
||||||
|
keyPEM, err := base64.StdEncoding.DecodeString(keyString)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("Failed to parse base64 key string: %v", err)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
keyBlock, _ := pem.Decode([]byte(keyPEM))
|
||||||
|
if keyBlock == nil {
|
||||||
|
err := fmt.Errorf("Failed to parse key PEM")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
switch keyBlock.Type {
|
||||||
|
case "PRIVATE KEY":
|
||||||
|
res, err = x509.ParsePKCS8PrivateKey(keyBlock.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
case "RSA PRIVATE KEY":
|
||||||
|
res, err = x509.ParsePKCS1PrivateKey(keyBlock.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
case "EC PRIVATE KEY":
|
||||||
|
res, err = x509.ParseECPrivateKey(keyBlock.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
err := fmt.Errorf("Unknown PEM key type: %s", keyBlock.Type)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseEncodedKey(keyPEM string) (any, error) {
|
||||||
|
var err error
|
||||||
|
var res any
|
||||||
|
|
||||||
|
keyBlock, _ := pem.Decode([]byte(keyPEM))
|
||||||
|
if keyBlock == nil {
|
||||||
|
err := fmt.Errorf("Failed to parse key PEM")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
switch keyBlock.Type {
|
||||||
|
case "PRIVATE KEY":
|
||||||
|
res, err = x509.ParsePKCS8PrivateKey(keyBlock.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
case "RSA PRIVATE KEY":
|
||||||
|
res, err = x509.ParsePKCS1PrivateKey(keyBlock.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
case "EC PRIVATE KEY":
|
||||||
|
res, err = x509.ParseECPrivateKey(keyBlock.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
err := fmt.Errorf("Unknown PEM key type: %s", keyBlock.Type)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckDoubleEncodedCertificateChain(topIssuerCN string, certStrings []string) ([]string, error) {
|
||||||
|
var err error
|
||||||
|
res := make([]string, 0)
|
||||||
|
|
||||||
|
certObjs := make([]*x509.Certificate, 0)
|
||||||
|
for _, certString := range certStrings {
|
||||||
|
certObj, err := ParseDoubleEncodedCerificate(certString)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
certObjs = append(certObjs, certObj)
|
||||||
|
}
|
||||||
|
|
||||||
|
issuerFound := false
|
||||||
|
issuerIndex := -1
|
||||||
|
for i, certObj := range certObjs {
|
||||||
|
if topIssuerCN == certObj.Subject.String() {
|
||||||
|
issuerIndex = i
|
||||||
|
issuerFound = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !issuerFound {
|
||||||
|
err := fmt.Errorf("Issuer for %s cannot found", topIssuerCN)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
interCertObj := certObjs[issuerIndex]
|
||||||
|
interCertString := certStrings[issuerIndex]
|
||||||
|
if !interCertObj.IsCA {
|
||||||
|
err := fmt.Errorf("Issuer %s is not CA", interCertObj.Subject.String())
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
expired := interCertObj.NotAfter.Before(time.Now())
|
||||||
|
if !expired {
|
||||||
|
err := fmt.Errorf("Issuer %s expired %v", interCertObj.Subject.String(), interCertObj.NotAfter)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res = append(res, interCertString)
|
||||||
|
if interCertObj.Subject.String() == interCertObj.Issuer.String() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
updatedCertStrings := append(certStrings[:issuerIndex], certStrings[issuerIndex+1:]...)
|
||||||
|
topIssuerCN = interCertObj.Issuer.String()
|
||||||
|
|
||||||
|
certStringsTail, err := CheckDoubleEncodedCertificateChain(topIssuerCN, updatedCertStrings)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res = append(res, certStringsTail...)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package cm509
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCertChainCheckerErr(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
certBytes, err := os.ReadFile("testchain_a01.crt")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotZero(t, len(certBytes))
|
||||||
|
certObj, err := ParseEncodedCerificate(string(certBytes))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, certObj)
|
||||||
|
|
||||||
|
certStrings := make([]string, 0)
|
||||||
|
for i := 1; i < 4; i++ {
|
||||||
|
certBytes, err := os.ReadFile(fmt.Sprintf("testchain_a%02d.crt", i))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotZero(t, len(certBytes))
|
||||||
|
certString := base64.StdEncoding.EncodeToString(certBytes)
|
||||||
|
certStrings = append(certStrings, certString)
|
||||||
|
}
|
||||||
|
topIssuerCN := certObj.Issuer.String()
|
||||||
|
|
||||||
|
_, err = CheckDoubleEncodedCertificateChain(topIssuerCN, certStrings)
|
||||||
|
require.Error(t, err)
|
||||||
|
//require.NotNil(t, resString)
|
||||||
|
//require.NotZero(t, len(resString))
|
||||||
|
}
|
||||||
|
|
||||||
|
func printObj(label string, obj any) {
|
||||||
|
objBytes, _ := yaml.Marshal(obj)
|
||||||
|
objString := string(objBytes)
|
||||||
|
if strings.Count(objString, "\n") < 2 {
|
||||||
|
fmt.Printf("==== %s: %s\n", label, objString)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("==== %s ::\n%s\n", label, objString)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
package common
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||||
|
*/
|
||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
mtx sync.Mutex
|
||||||
|
output io.WriteCloser = os.Stderr
|
||||||
|
)
|
||||||
|
|
||||||
|
type Logger struct {
|
||||||
|
subject string
|
||||||
|
writer io.WriteCloser
|
||||||
|
mtx *sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLogger(subj string) *Logger {
|
||||||
|
return &Logger{
|
||||||
|
subject: subj,
|
||||||
|
writer: output,
|
||||||
|
mtx: &mtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func SetWriter(newOut io.WriteCloser) {
|
||||||
|
mtx.Lock()
|
||||||
|
output = newOut
|
||||||
|
mtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (logg *Logger) SetWriter(newOut io.WriteCloser) {
|
||||||
|
mtx.Lock()
|
||||||
|
logg.writer = newOut
|
||||||
|
var newMtx sync.Mutex
|
||||||
|
logg.mtx = &newMtx
|
||||||
|
mtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (logg *Logger) Debugf(message string, args ...any) {
|
||||||
|
logg.printf("debug", message, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (logg *Logger) Infof(message string, args ...any) {
|
||||||
|
logg.printf("info", message, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (logg *Logger) Warningf(message string, args ...any) {
|
||||||
|
logg.printf("warning", message, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (logg *Logger) Errorf(message string, args ...any) {
|
||||||
|
logg.printf("error", message, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (logg *Logger) printf(level, message string, args ...any) {
|
||||||
|
timestamp := time.Now().Format(time.RFC3339)
|
||||||
|
buffer := bytes.NewBuffer([]byte{})
|
||||||
|
if logg.subject != "" {
|
||||||
|
fmt.Fprintf(buffer, "%s %s.%s: ", timestamp, logg.subject, level)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(buffer, "%s %s: ", timestamp, level)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(buffer, message, args...)
|
||||||
|
fmt.Fprintf(buffer, "\n")
|
||||||
|
logg.mtx.Lock()
|
||||||
|
fmt.Fprint(output, buffer.String())
|
||||||
|
logg.mtx.Unlock()
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||||
|
*/
|
||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLogger(t *testing.T) {
|
||||||
|
devNull, err := os.OpenFile("/dev/null", os.O_RDWR, 0666)
|
||||||
|
require.NoError(t, err)
|
||||||
|
SetWriter(devNull)
|
||||||
|
logg := NewLogger("test")
|
||||||
|
logg.Debugf("foo: %s", "bar")
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkLoggerL(b *testing.B) {
|
||||||
|
devNull, err := os.OpenFile("/dev/null", os.O_RDWR, 0666)
|
||||||
|
require.NoError(b, err)
|
||||||
|
SetWriter(devNull)
|
||||||
|
logg := NewLogger("test")
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
logg.Debugf("foo: %s", "bar")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkLoggerP(b *testing.B) {
|
||||||
|
devNull, err := os.OpenFile("/dev/null", os.O_RDWR, 0666)
|
||||||
|
require.NoError(b, err)
|
||||||
|
logg := NewLogger("test")
|
||||||
|
b.ResetTimer()
|
||||||
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
|
for pb.Next() {
|
||||||
|
logg.Debugf("foo: %s", "bar")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,452 @@
|
|||||||
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-grpc v1.3.0
|
||||||
|
// - protoc v3.21.12
|
||||||
|
// source: mbctl.proto
|
||||||
|
|
||||||
|
package mbctl
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
grpc "google.golang.org/grpc"
|
||||||
|
codes "google.golang.org/grpc/codes"
|
||||||
|
status "google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the grpc package it is being compiled against.
|
||||||
|
// Requires gRPC-Go v1.62.0 or later.
|
||||||
|
const _ = grpc.SupportPackageIsVersion8
|
||||||
|
|
||||||
|
const (
|
||||||
|
Control_GetHello_FullMethodName = "/mbasecontrol.Control/getHello"
|
||||||
|
Control_CreateAccount_FullMethodName = "/mbasecontrol.Control/createAccount"
|
||||||
|
Control_DeleteAccount_FullMethodName = "/mbasecontrol.Control/deleteAccount"
|
||||||
|
Control_UpdateAccount_FullMethodName = "/mbasecontrol.Control/updateAccount"
|
||||||
|
Control_GetAccount_FullMethodName = "/mbasecontrol.Control/getAccount"
|
||||||
|
Control_ListAccounts_FullMethodName = "/mbasecontrol.Control/listAccounts"
|
||||||
|
Control_SetGrant_FullMethodName = "/mbasecontrol.Control/setGrant"
|
||||||
|
Control_DeleteGrant_FullMethodName = "/mbasecontrol.Control/deleteGrant"
|
||||||
|
Control_GetDump_FullMethodName = "/mbasecontrol.Control/getDump"
|
||||||
|
Control_RestoreDump_FullMethodName = "/mbasecontrol.Control/restoreDump"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ControlClient is the client API for Control service.
|
||||||
|
//
|
||||||
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||||
|
type ControlClient interface {
|
||||||
|
GetHello(ctx context.Context, in *GetHelloParams, opts ...grpc.CallOption) (*GetHelloResult, error)
|
||||||
|
CreateAccount(ctx context.Context, in *CreateAccountParams, opts ...grpc.CallOption) (*CreateAccountResult, error)
|
||||||
|
DeleteAccount(ctx context.Context, in *DeleteAccountParams, opts ...grpc.CallOption) (*DeleteAccountResult, error)
|
||||||
|
UpdateAccount(ctx context.Context, in *UpdateAccountParams, opts ...grpc.CallOption) (*UpdateAccountResult, error)
|
||||||
|
GetAccount(ctx context.Context, in *GetAccountParams, opts ...grpc.CallOption) (*GetAccountResult, error)
|
||||||
|
ListAccounts(ctx context.Context, in *ListAccountsParams, opts ...grpc.CallOption) (*ListAccountsResult, error)
|
||||||
|
SetGrant(ctx context.Context, in *SetGrantParams, opts ...grpc.CallOption) (*SetGrantResult, error)
|
||||||
|
DeleteGrant(ctx context.Context, in *DeleteGrantParams, opts ...grpc.CallOption) (*DeleteGrantResult, error)
|
||||||
|
GetDump(ctx context.Context, in *GetDumpParams, opts ...grpc.CallOption) (*GetDumpResult, error)
|
||||||
|
RestoreDump(ctx context.Context, in *RestoreDumpParams, opts ...grpc.CallOption) (*RestoreDumpResult, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type controlClient struct {
|
||||||
|
cc grpc.ClientConnInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewControlClient(cc grpc.ClientConnInterface) ControlClient {
|
||||||
|
return &controlClient{cc}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controlClient) GetHello(ctx context.Context, in *GetHelloParams, opts ...grpc.CallOption) (*GetHelloResult, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(GetHelloResult)
|
||||||
|
err := c.cc.Invoke(ctx, Control_GetHello_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controlClient) CreateAccount(ctx context.Context, in *CreateAccountParams, opts ...grpc.CallOption) (*CreateAccountResult, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(CreateAccountResult)
|
||||||
|
err := c.cc.Invoke(ctx, Control_CreateAccount_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controlClient) DeleteAccount(ctx context.Context, in *DeleteAccountParams, opts ...grpc.CallOption) (*DeleteAccountResult, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(DeleteAccountResult)
|
||||||
|
err := c.cc.Invoke(ctx, Control_DeleteAccount_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controlClient) UpdateAccount(ctx context.Context, in *UpdateAccountParams, opts ...grpc.CallOption) (*UpdateAccountResult, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(UpdateAccountResult)
|
||||||
|
err := c.cc.Invoke(ctx, Control_UpdateAccount_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controlClient) GetAccount(ctx context.Context, in *GetAccountParams, opts ...grpc.CallOption) (*GetAccountResult, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(GetAccountResult)
|
||||||
|
err := c.cc.Invoke(ctx, Control_GetAccount_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controlClient) ListAccounts(ctx context.Context, in *ListAccountsParams, opts ...grpc.CallOption) (*ListAccountsResult, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(ListAccountsResult)
|
||||||
|
err := c.cc.Invoke(ctx, Control_ListAccounts_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controlClient) SetGrant(ctx context.Context, in *SetGrantParams, opts ...grpc.CallOption) (*SetGrantResult, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(SetGrantResult)
|
||||||
|
err := c.cc.Invoke(ctx, Control_SetGrant_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controlClient) DeleteGrant(ctx context.Context, in *DeleteGrantParams, opts ...grpc.CallOption) (*DeleteGrantResult, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(DeleteGrantResult)
|
||||||
|
err := c.cc.Invoke(ctx, Control_DeleteGrant_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controlClient) GetDump(ctx context.Context, in *GetDumpParams, opts ...grpc.CallOption) (*GetDumpResult, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(GetDumpResult)
|
||||||
|
err := c.cc.Invoke(ctx, Control_GetDump_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controlClient) RestoreDump(ctx context.Context, in *RestoreDumpParams, opts ...grpc.CallOption) (*RestoreDumpResult, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(RestoreDumpResult)
|
||||||
|
err := c.cc.Invoke(ctx, Control_RestoreDump_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ControlServer is the server API for Control service.
|
||||||
|
// All implementations must embed UnimplementedControlServer
|
||||||
|
// for forward compatibility
|
||||||
|
type ControlServer interface {
|
||||||
|
GetHello(context.Context, *GetHelloParams) (*GetHelloResult, error)
|
||||||
|
CreateAccount(context.Context, *CreateAccountParams) (*CreateAccountResult, error)
|
||||||
|
DeleteAccount(context.Context, *DeleteAccountParams) (*DeleteAccountResult, error)
|
||||||
|
UpdateAccount(context.Context, *UpdateAccountParams) (*UpdateAccountResult, error)
|
||||||
|
GetAccount(context.Context, *GetAccountParams) (*GetAccountResult, error)
|
||||||
|
ListAccounts(context.Context, *ListAccountsParams) (*ListAccountsResult, error)
|
||||||
|
SetGrant(context.Context, *SetGrantParams) (*SetGrantResult, error)
|
||||||
|
DeleteGrant(context.Context, *DeleteGrantParams) (*DeleteGrantResult, error)
|
||||||
|
GetDump(context.Context, *GetDumpParams) (*GetDumpResult, error)
|
||||||
|
RestoreDump(context.Context, *RestoreDumpParams) (*RestoreDumpResult, error)
|
||||||
|
mustEmbedUnimplementedControlServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnimplementedControlServer must be embedded to have forward compatible implementations.
|
||||||
|
type UnimplementedControlServer struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UnimplementedControlServer) GetHello(context.Context, *GetHelloParams) (*GetHelloResult, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method GetHello not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedControlServer) CreateAccount(context.Context, *CreateAccountParams) (*CreateAccountResult, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method CreateAccount not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedControlServer) DeleteAccount(context.Context, *DeleteAccountParams) (*DeleteAccountResult, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method DeleteAccount not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedControlServer) UpdateAccount(context.Context, *UpdateAccountParams) (*UpdateAccountResult, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method UpdateAccount not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedControlServer) GetAccount(context.Context, *GetAccountParams) (*GetAccountResult, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method GetAccount not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedControlServer) ListAccounts(context.Context, *ListAccountsParams) (*ListAccountsResult, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method ListAccounts not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedControlServer) SetGrant(context.Context, *SetGrantParams) (*SetGrantResult, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method SetGrant not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedControlServer) DeleteGrant(context.Context, *DeleteGrantParams) (*DeleteGrantResult, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method DeleteGrant not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedControlServer) GetDump(context.Context, *GetDumpParams) (*GetDumpResult, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method GetDump not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedControlServer) RestoreDump(context.Context, *RestoreDumpParams) (*RestoreDumpResult, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method RestoreDump not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedControlServer) mustEmbedUnimplementedControlServer() {}
|
||||||
|
|
||||||
|
// UnsafeControlServer may be embedded to opt out of forward compatibility for this service.
|
||||||
|
// Use of this interface is not recommended, as added methods to ControlServer will
|
||||||
|
// result in compilation errors.
|
||||||
|
type UnsafeControlServer interface {
|
||||||
|
mustEmbedUnimplementedControlServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterControlServer(s grpc.ServiceRegistrar, srv ControlServer) {
|
||||||
|
s.RegisterService(&Control_ServiceDesc, srv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Control_GetHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(GetHelloParams)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(ControlServer).GetHello(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: Control_GetHello_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(ControlServer).GetHello(ctx, req.(*GetHelloParams))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Control_CreateAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(CreateAccountParams)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(ControlServer).CreateAccount(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: Control_CreateAccount_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(ControlServer).CreateAccount(ctx, req.(*CreateAccountParams))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Control_DeleteAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(DeleteAccountParams)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(ControlServer).DeleteAccount(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: Control_DeleteAccount_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(ControlServer).DeleteAccount(ctx, req.(*DeleteAccountParams))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Control_UpdateAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(UpdateAccountParams)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(ControlServer).UpdateAccount(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: Control_UpdateAccount_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(ControlServer).UpdateAccount(ctx, req.(*UpdateAccountParams))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Control_GetAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(GetAccountParams)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(ControlServer).GetAccount(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: Control_GetAccount_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(ControlServer).GetAccount(ctx, req.(*GetAccountParams))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Control_ListAccounts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(ListAccountsParams)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(ControlServer).ListAccounts(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: Control_ListAccounts_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(ControlServer).ListAccounts(ctx, req.(*ListAccountsParams))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Control_SetGrant_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(SetGrantParams)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(ControlServer).SetGrant(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: Control_SetGrant_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(ControlServer).SetGrant(ctx, req.(*SetGrantParams))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Control_DeleteGrant_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(DeleteGrantParams)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(ControlServer).DeleteGrant(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: Control_DeleteGrant_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(ControlServer).DeleteGrant(ctx, req.(*DeleteGrantParams))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Control_GetDump_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(GetDumpParams)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(ControlServer).GetDump(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: Control_GetDump_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(ControlServer).GetDump(ctx, req.(*GetDumpParams))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Control_RestoreDump_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(RestoreDumpParams)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(ControlServer).RestoreDump(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: Control_RestoreDump_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(ControlServer).RestoreDump(ctx, req.(*RestoreDumpParams))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Control_ServiceDesc is the grpc.ServiceDesc for Control service.
|
||||||
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
|
// and not to be introspected or modified (even as a copy)
|
||||||
|
var Control_ServiceDesc = grpc.ServiceDesc{
|
||||||
|
ServiceName: "mbasecontrol.Control",
|
||||||
|
HandlerType: (*ControlServer)(nil),
|
||||||
|
Methods: []grpc.MethodDesc{
|
||||||
|
{
|
||||||
|
MethodName: "getHello",
|
||||||
|
Handler: _Control_GetHello_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "createAccount",
|
||||||
|
Handler: _Control_CreateAccount_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "deleteAccount",
|
||||||
|
Handler: _Control_DeleteAccount_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "updateAccount",
|
||||||
|
Handler: _Control_UpdateAccount_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "getAccount",
|
||||||
|
Handler: _Control_GetAccount_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "listAccounts",
|
||||||
|
Handler: _Control_ListAccounts_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "setGrant",
|
||||||
|
Handler: _Control_SetGrant_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "deleteGrant",
|
||||||
|
Handler: _Control_DeleteGrant_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "getDump",
|
||||||
|
Handler: _Control_GetDump_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "restoreDump",
|
||||||
|
Handler: _Control_RestoreDump_Handler,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Streams: []grpc.StreamDesc{},
|
||||||
|
Metadata: "mbctl.proto",
|
||||||
|
}
|
||||||
@@ -0,0 +1,190 @@
|
|||||||
|
package netacl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NetACL struct {
|
||||||
|
enabledAddresses []netip.Addr
|
||||||
|
enabledNetworks []netip.Prefix
|
||||||
|
disabledAddresses []netip.Addr
|
||||||
|
disabledNetworks []netip.Prefix
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNetACL() *NetACL {
|
||||||
|
return &NetACL{
|
||||||
|
enabledAddresses: make([]netip.Addr, 0),
|
||||||
|
enabledNetworks: make([]netip.Prefix, 0),
|
||||||
|
disabledAddresses: make([]netip.Addr, 0),
|
||||||
|
disabledNetworks: make([]netip.Prefix, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type netACL struct {
|
||||||
|
EnabledAddresses []string `json:"enabledAddresses" yaml:"enabledAddresses"`
|
||||||
|
EnabledNetworks []string `json:"enabledNetworks" yaml:"enabledNetworks"`
|
||||||
|
DisabledAddresses []string `json:"disabledAddresses" yaml:"disabledAddresses"`
|
||||||
|
DisabledNetworks []string `json:"disabledNetworks" yaml:"disabledNetworks"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func newNetACL() *netACL {
|
||||||
|
return &netACL{
|
||||||
|
EnabledAddresses: make([]string, 0),
|
||||||
|
EnabledNetworks: make([]string, 0),
|
||||||
|
DisabledAddresses: make([]string, 0),
|
||||||
|
DisabledNetworks: make([]string, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (al *NetACL) MarshalJSON() ([]byte, error) {
|
||||||
|
alDescr := newNetACL()
|
||||||
|
for _, disabledAddress := range al.disabledAddresses {
|
||||||
|
alDescr.DisabledAddresses = append(alDescr.DisabledAddresses, disabledAddress.String())
|
||||||
|
}
|
||||||
|
for _, disabledNetwork := range al.disabledNetworks {
|
||||||
|
alDescr.DisabledNetworks = append(alDescr.DisabledNetworks, disabledNetwork.String())
|
||||||
|
}
|
||||||
|
for _, enabledAddress := range al.enabledAddresses {
|
||||||
|
alDescr.EnabledAddresses = append(alDescr.EnabledAddresses, enabledAddress.String())
|
||||||
|
}
|
||||||
|
for _, enabledNetwork := range al.enabledNetworks {
|
||||||
|
alDescr.EnabledNetworks = append(alDescr.EnabledNetworks, enabledNetwork.String())
|
||||||
|
}
|
||||||
|
return json.Marshal(alDescr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (al *NetACL) UnmarshalJSON(data []byte) error {
|
||||||
|
var err error
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (al *NetACL) MarshalYAML() ([]byte, error) {
|
||||||
|
alDescr := newNetACL()
|
||||||
|
for _, disabledAddress := range al.disabledAddresses {
|
||||||
|
alDescr.DisabledAddresses = append(alDescr.DisabledAddresses, disabledAddress.String())
|
||||||
|
}
|
||||||
|
for _, disabledNetwork := range al.disabledNetworks {
|
||||||
|
alDescr.DisabledNetworks = append(alDescr.DisabledNetworks, disabledNetwork.String())
|
||||||
|
}
|
||||||
|
for _, enabledAddress := range al.enabledAddresses {
|
||||||
|
alDescr.EnabledAddresses = append(alDescr.EnabledAddresses, enabledAddress.String())
|
||||||
|
}
|
||||||
|
for _, enabledNetwork := range al.enabledNetworks {
|
||||||
|
alDescr.EnabledNetworks = append(alDescr.EnabledNetworks, enabledNetwork.String())
|
||||||
|
}
|
||||||
|
return yaml.Marshal(alDescr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (al *NetACL) UnmarshalYAML(data []byte) error {
|
||||||
|
var err error
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (al *NetACL) AddressIsEnabled(address string) (bool, error) {
|
||||||
|
var err error
|
||||||
|
var res bool
|
||||||
|
addr, err := netip.ParseAddr(address)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
for _, disabledAddr := range al.disabledAddresses {
|
||||||
|
if disabledAddr.Compare(addr) == 0 {
|
||||||
|
res = false
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, disabledNetwork := range al.disabledNetworks {
|
||||||
|
if disabledNetwork.Contains(addr) {
|
||||||
|
res = false
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, enabledAddr := range al.enabledAddresses {
|
||||||
|
if enabledAddr.Compare(addr) == 0 {
|
||||||
|
res = true
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, enabledNetwork := range al.enabledNetworks {
|
||||||
|
if enabledNetwork.Contains(addr) {
|
||||||
|
res = true
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (al *NetACL) AddrIsEnabled(addr netip.Addr) (bool, error) {
|
||||||
|
var err error
|
||||||
|
var res bool
|
||||||
|
for _, disabledAddr := range al.disabledAddresses {
|
||||||
|
if disabledAddr.Compare(addr) == 0 {
|
||||||
|
res = false
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, disabledNetwork := range al.disabledNetworks {
|
||||||
|
if disabledNetwork.Contains(addr) {
|
||||||
|
res = false
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, enabledAddr := range al.enabledAddresses {
|
||||||
|
if enabledAddr.Compare(addr) == 0 {
|
||||||
|
res = true
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, enabledNetwork := range al.enabledNetworks {
|
||||||
|
if enabledNetwork.Contains(addr) {
|
||||||
|
res = true
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (al *NetACL) AddEnabledAddresses(addresses ...string) error {
|
||||||
|
var err error
|
||||||
|
for _, address := range addresses {
|
||||||
|
addr, addrParseErr := netip.ParseAddr(address)
|
||||||
|
if addrParseErr == nil {
|
||||||
|
al.enabledAddresses = append(al.enabledAddresses, addr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
prefix, prefixParseErr := netip.ParsePrefix(address)
|
||||||
|
if prefixParseErr == nil {
|
||||||
|
al.enabledNetworks = append(al.enabledNetworks, prefix)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
err = errors.Join(addrParseErr, prefixParseErr)
|
||||||
|
err = fmt.Errorf("Address %s is not correct, error: %v", address, err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (al *NetACL) AddDisabledAddresses(addresses ...string) error {
|
||||||
|
var err error
|
||||||
|
for _, address := range addresses {
|
||||||
|
addr, addrParseErr := netip.ParseAddr(address)
|
||||||
|
if addrParseErr == nil {
|
||||||
|
al.disabledAddresses = append(al.disabledAddresses, addr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
prefix, prefixParseErr := netip.ParsePrefix(address)
|
||||||
|
if prefixParseErr == nil {
|
||||||
|
al.disabledNetworks = append(al.disabledNetworks, prefix)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
err = errors.Join(addrParseErr, prefixParseErr)
|
||||||
|
err = fmt.Errorf("Address %s is not correct, error: %v", address, err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package netacl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNetACLComplex(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
var enabled bool
|
||||||
|
al := NewNetACL()
|
||||||
|
require.NotNil(t, al)
|
||||||
|
err = al.AddDisabledAddresses("10.0.0.1")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = al.AddDisabledAddresses("192.168.10.0/24")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = al.AddEnabledAddresses("192.168.100.0/16")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
yamlData, err := yaml.Marshal(al)
|
||||||
|
require.NoError(t, err)
|
||||||
|
fmt.Printf("\n%s\n", string(yamlData))
|
||||||
|
|
||||||
|
enabled, err = al.AddressIsEnabled("8.7.7.7")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, false, enabled)
|
||||||
|
|
||||||
|
enabled, err = al.AddressIsEnabled("192.168.10.0")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, false, enabled)
|
||||||
|
|
||||||
|
enabled, err = al.AddressIsEnabled("192.168.100.7")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, true, enabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNetACLAllEnabled(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
var enabled bool
|
||||||
|
al := NewNetACL()
|
||||||
|
require.NotNil(t, al)
|
||||||
|
err = al.AddEnabledAddresses("0.0.0.1/0")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = al.AddEnabledAddresses("10.0.1.1/17")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
yamlData, err := yaml.Marshal(al)
|
||||||
|
require.NoError(t, err)
|
||||||
|
fmt.Printf("\n%s\n", string(yamlData))
|
||||||
|
|
||||||
|
enabled, err = al.AddressIsEnabled("192.168.100.7")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, true, enabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNetACLLoopEnabled(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
var enabled bool
|
||||||
|
al := NewNetACL()
|
||||||
|
require.NotNil(t, al)
|
||||||
|
err = al.AddEnabledAddresses("::1/0")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
yamlData, err := yaml.Marshal(al)
|
||||||
|
require.NoError(t, err)
|
||||||
|
fmt.Printf("\n%s\n", string(yamlData))
|
||||||
|
|
||||||
|
enabled, err = al.AddressIsEnabled("::1")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, true, enabled)
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
option go_package = ".;mbctl";
|
||||||
|
|
||||||
|
package mbasecontrol;
|
||||||
|
|
||||||
|
service Control {
|
||||||
|
rpc getHello(getHelloParams) returns (getHelloResult) {};
|
||||||
|
|
||||||
|
rpc createAccount(createAccountParams) returns (createAccountResult) {};
|
||||||
|
rpc deleteAccount(deleteAccountParams) returns (deleteAccountResult) {};
|
||||||
|
rpc updateAccount(updateAccountParams) returns (updateAccountResult) {};
|
||||||
|
rpc getAccount(getAccountParams) returns (getAccountResult) {};
|
||||||
|
rpc listAccounts(listAccountsParams) returns (listAccountsResult) {};
|
||||||
|
|
||||||
|
rpc setGrant(setGrantParams) returns (setGrantResult) {};
|
||||||
|
rpc deleteGrant(deleteGrantParams) returns (deleteGrantResult) {};
|
||||||
|
|
||||||
|
rpc getDump(getDumpParams) returns (getDumpResult) {};
|
||||||
|
rpc restoreDump(restoreDumpParams) returns (restoreDumpResult) {};
|
||||||
|
}
|
||||||
|
|
||||||
|
message getDumpParams {}
|
||||||
|
message getDumpResult {
|
||||||
|
string dump = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message restoreDumpParams {
|
||||||
|
string dump = 1;
|
||||||
|
bool deleteAllRecords = 2;
|
||||||
|
}
|
||||||
|
message restoreDumpResult {
|
||||||
|
}
|
||||||
|
|
||||||
|
message setGrantParams {
|
||||||
|
string username = 1;
|
||||||
|
int64 accountID = 2;
|
||||||
|
string operation = 3;
|
||||||
|
}
|
||||||
|
message setGrantResult {
|
||||||
|
int64 grantID = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message deleteGrantParams {
|
||||||
|
string username = 1;
|
||||||
|
int64 accountID = 2;
|
||||||
|
string operation = 3;
|
||||||
|
}
|
||||||
|
message deleteGrantResult {}
|
||||||
|
|
||||||
|
|
||||||
|
message createAccountParams {
|
||||||
|
string username = 1;
|
||||||
|
string password = 2;
|
||||||
|
}
|
||||||
|
message createAccountResult {
|
||||||
|
int64 accountID = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message deleteAccountParams {
|
||||||
|
string username = 1;
|
||||||
|
int64 accountID = 2;
|
||||||
|
}
|
||||||
|
message deleteAccountResult {}
|
||||||
|
|
||||||
|
message updateAccountParams {
|
||||||
|
string username = 1;
|
||||||
|
int64 accountID = 2;
|
||||||
|
string newUsername = 3;
|
||||||
|
string newPassword = 4;
|
||||||
|
bool disabled = 5;
|
||||||
|
}
|
||||||
|
message updateAccountResult {}
|
||||||
|
|
||||||
|
message getAccountParams {}
|
||||||
|
message getAccountResult {}
|
||||||
|
|
||||||
|
message listAccountsParams {}
|
||||||
|
message listAccountsResult {
|
||||||
|
repeated accountShortDescr accounts = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message accountShortDescr {
|
||||||
|
string username = 1;
|
||||||
|
bool disabled = 2;
|
||||||
|
string createdAt = 3;
|
||||||
|
string updatedAt = 4;
|
||||||
|
repeated grantShortDescr grants = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message grantShortDescr {
|
||||||
|
string operation = 1;
|
||||||
|
string createdAt = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message getHelloParams {}
|
||||||
|
message getHelloResult {
|
||||||
|
string message = 1;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user