How to add new entry to LDAP server with Golang? - go

I had an issue trying to add a new entry into my LDAP server. The error I get is the following: LDAP Result Code 65 "Object Class Violation": no structural object class provided. If anyone could give me some input on why, that would be helpful.
I'm binded to the server, so it seems like I just have an issue with the actual entry attributes.. but I'm not sure where to fix it.
package main
import (
"fmt"
// "github.com/go-ldap/ldap"
"gopkg.in/ldap.v2"
"log"
)
//List of constants
const (
host = "127.0.0.1"
port = "389"
hostPort = host + ":" + port
userID = "cn=admin,dc=test123,dc=com"
password = "password"
)
//Main function to be called
func main() {
addEntries()
}
//Add entries function
func addEntries(){
fmt.Println("Adding started")
//Initialize connection
l, err := ldap.Dial("tcp", hostPort)
if err != nil {
log.Fatal(err)
}
defer l.Close()
//Bind to the LDAP server
bindusername := "cn=admin,dc=test123,dc=com"
bindpassword := "password"
err = l.Bind(bindusername, bindpassword)
if err != nil {
log.Fatal(err)
return
}
fmt.Println("Testing.")
//Create new Add request object to be added to LDAP server.
a := ldap.NewAddRequest("ou=groups,dc=test123,dc=com")
a.Attribute("cn", []string{"gotest"})
a.Attribute("objectClass" ,[]string{"top"})
a.Attribute("description", []string{"this is a test to add an entry using golang"})
a.Attribute("sn" ,[]string{"Google"})
fmt.Println("Testing.")
add(a , l)
}
func add(addRequest *ldap.AddRequest , l *ldap.Conn) {
err := l.Add(addRequest)
if err != nil {
fmt.Println("Entry NOT done",err)
} else {
fmt.Println("Entry DONE",err)
}
}

The most common errors when creating LDAP objects is a missing objectClass and/or an object's mandatory attributes (e.g. uid, cn etc.) Here are some techniques to identify these requirements.
You can query an LDAP server's schema like so:
ldapsearch -x -h my.example.com -b "cn=schema" -s base "(objectclass=*)"
The output is not very human-readable, but if you know the exact objectClass you are looking for, things can become a little clearer.
For example the objectClass: person definition may looks like this:
objectClasses: ( 2.5.6.6 NAME 'person' DESC 'Defines entries that generically
represent people.' SUP top STRUCTURAL MUST ( cn $ sn ) MAY ( description $ se
eAlso $ telephoneNumber $ userPassword ) )
So you can see this is a STRUCTURAL objectClass (supplementing top) and if one were to create such a person LDAP object, it:
must include: cn and sn
and optionally: description, seeAlso, telephoneNumber or userPassword
Individual attribute types are defined like so:
attributeTypes: ( 2.5.4.3 NAME ( 'cn' 'commonName' ) DESC 'This is the X.500 c
ommonName attribute, which contains a name of an object. If the object corre
sponds to a person, it is typically the persons full name.' SUP 2.5.4.41 EQUA
LITY 2.5.13.2 ORDERING 2.5.13.3 SUBSTR 2.5.13.4 )

Related

Checking for Empty Integer in Golang

I am designing an API where a user sends integer values and some operation is performed depending on the value sent. During the validation check that whether this value exists in the request, I have to equate it to 0 i.e. if intValue == 0.
However, I also have to perform a different operation in case the value is 0. Is there any way I can check that the integer does not exist or is empty without equating to 0?
Note: The requirements are set by the client and I cannot change them.
When decoding JSON data into a struct, you can differentiate optional fields by declaring them as a pointer type.
For example:
type requestFormat struct {
AlwaysPresent int
OptionalValue *int
}
Now when the value is decoded, you can check if the value was supplied at all:
var data requestFormat
err := json.NewDecoder(request.Body).Decode(&data)
if err != nil { ... }
if data.OptionalValue == nil {
// OptionalValue was not defined in the JSON data
} else {
// OptionalValue was defined, but it still may have been 0
val := *data.OptionalValue
}
in production as #phuclv say
there's no such thing as an "empty integer"
inelegant implementation
check if it is required:
like
#Hymns For Disco use json.NewDecoder
or
validators
but it is being abandoned:
Why required and optional is removed in Protocol Buffers 3
another way:
use map but struct,which can tell if a field exists
follow is a example
package main
import (
"encoding/json"
"io/ioutil"
"net/http"
)
type Test struct {
Name string
Age int
}
func testJson(w http.ResponseWriter, r *http.Request) {
aMap := make(map[string]interface{})
data, _ := ioutil.ReadAll(r.Body)
json.Unmarshal(data, &aMap)
test := Test{}
json.Unmarshal(data, &test)
}
func main() {
http.HandleFunc("/", testJson)
http.ListenAndServe(":8080", nil)
}

How to use Go / GORM to print SELECT query output without pre-defined struct

I am developing an API using Go which connects to MySQL database for some query execution. Am using GORM for database operations. But am stuck at printing the SELECT query output for the tables which I don't have the column names.
My use case is that, I need to run the query on multiple tables where I don't have an idea about what their column names and types are. And so I cannot pre-define a struct for all the current and future tables which might get added.
Is there a way to print/save the SELECT query output without a pre-defined struct ?
I tried do some using empty struct but it didn't help me.
P.S: Am a beginner in Go
type Testing struct{}
var test Testing
dsn := fmt.Sprintf("%v:%v#tcp(%v:%v)/%v", myds.DBuser, myds.DBpassword, myds.DBhost, myds.DBport, myds.DBname)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Println(err)
}
tx := db.Raw(query).Scan(&test)
if tx.Error != nil {
fmt.Println(tx.Error)
}
fmt.Println(test)
You can use an anonymous struct
Let's say you have a struct:
type User struct{
FirstName string
LastName string
}
Query:
SELECT CONCAT(first_name,last_name) AS full_name from users;
Notice the new column full_name
you can simply do
var fullName = struct{FullName string}{}
Notice how I use pascal case & FullName has to be the field name
A capital letter in between will represent a _
Field is public so it can be accessed outside.
full_name(query) = FullName(field)
pass this fullName object as a bucket to your Scan and it should work.
db.Raw(query).Scan(&fullName)
EDIT:
Your query will have some result right?
Let me assume that you have
column_one,column_two... column_n
Now, to get the data from all the columns or selected ones if you want, you simply have to define fields (in anonymous struct) with specific names. In our case:
struct{ColumnOne,ColumnTwo,..ColumnN interface{}}{}
P.S. I have used interface{}, you can use types depending on the data your column returns.
It worked for me by using a map type with interface. This helped me to save the SELECT query results without pre-defined struct or the column names.
dsn := fmt.Sprintf("%v:%v#tcp(%v:%v)/%v", myds.DBuser, myds.DBpassword, myds.DBhost, myds.DBport, myds.DBname)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Println(err)
}
var result []map[string]interface{}
tx := db.Raw(query).Scan(&result)
if tx.Error != nil {
fmt.Println(tx.Error)
return
}
bytes, _ := json.Marshal(result)
fmt.Println(string(bytes))

Google Cloud Golang: How to parse project/zone/instance from instance URL?

I'm using compute.NewRegionInstanceGroupManagersService's ListManagedInstances call which returns ManagedInstance's.
ManagedInstance has a field Instance which is an instance url, like https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1-b/instances/instance-group-z0hf
Now I would like to get more details about this particular instance. So using InstanceService's Get call, the function signature looks like this:
func (r *InstancesService) Get(project string, zone string, instance string) *InstancesGetCall
What's the best way to parse the instance URL (see above) into its project, zone and instance parts? Or is there a way of using another method to pass the instance URL directly?
you could do something like this,
parse the URL to get its path
split the path by slash component
iterate the parts,
locate static strings
take the next value and assign it appropriately.
package main
import (
"fmt"
"net/url"
"strings"
)
func main() {
s := "https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1-b/instances/instance-group-z0hf"
u, err := url.Parse(s)
if err != nil {
panic(err)
}
parts := strings.Split(u.Path, "/")
var project string
var zone string
var inst string
for i := 0; i < len(parts); i++ {
if parts[i] == "projects" && i+1 < len(parts) {
project = parts[i+1]
i++
} else if parts[i] == "zones" && i+1 < len(parts) {
zone = parts[i+1]
i++
} else if parts[i] == "instances" && i+1 < len(parts) {
inst = parts[i+1]
i++
}
}
fmt.Println(project, zone, inst)
}
//Ouptput:
//my-project us-central1-b instance-group-z0hf
Alternatively, use the route engine from gorilla to create a new pattern, apply the route to the url path and collect output results. But it is more complex and probably not justified.
URLs are complex animals, the best way is using the library url.Parse. Then you can use a regex or split to extract the data you need from the path part.

sql.Rows to slice of strings

I'm using the standard go sql package to interface with AWS Athena.
My query returns for each record a uuid (string) and an array of emails.
Here is the code:
package main
import (
"fmt"
"database/sql"
_ "github.com/segmentio/go-athena"
_"encoding/json"
)
type Contact struct {
userid string
emails []string
}
func main() {
fmt.Println("hello")
db, err := sql.Open("athena", "db=example")
if err != nil {
panic(err)
}
rows, err := db.Query("SELECT userid, transform(value.emails, x -> x.value) from database LIMIT 10")
// Returns
// Row 1: "abc-123", ["email1#gmail.com", "email2#gmail.com"]
// Row 2: "def-456", ["email3#gmail.com"]
if err != nil {
panic(err)
}
for rows.Next() {
var contact Contact
rows.Scan(&contact.userid, &contact.emails)
fmt.Println(contact)
}
}
However, I get this error in the for loop:
panic: unknown type `array` with value [email1#gmail.com]
I'm confused about the array type mentioned and I can't make sense of the error.
How can I map the list of emails returned to a slice of strings in the Contact struct ?
Athena supports structural data types. For example the structural data type array:
Structural types
ARRAY < data_type >
From the message you get I assume the column email is of type ARRAY<VARCHAR>. In addition segmentio/go-athena panics on unsupported operations like Begin for a transaction (which are not supported in Athena). To read data in a Go array you have to put in some logic. See read "SELECT *" columns into []string in go or Read a Postgresql array directly into a Golang Slice for a starter. As you can see with the pq driver, reading an array might be implemented differently than just scanning a row

GORM Recursive Preloading

Using Go 1.10, and CockroachDB via the Postgres pq driver.
I have a GORM model that looks like this:
type User struct {
ID string `gorm:"type:UUID;primary_key;NOT_NULL"`
UserName string
... <other misc things here>
EnclosedUsers []User `gorm:"many2many:enclosed_user;jointable_foreignkey:parent_id;association_jointable_foreignkey:child_id"`
}
where ecnlosed_user is (specifically defined because reasons :) )
type EnclosedUsers struct {
ParentID string `gorm:"type:UUID;default:'00000000-0000-0000-0000-000000000000'"`
ChildID string `gorm:"type:UUID;default:'00000000-0000-0000-0000-000000000000'"`
}
That is, each user can have 0 or many enclosed users, and each user may have many parent users. Im trying to preload all of the enclosed users for each user, however GORM only preloads the first level.
i.e.:
usr1
|-> usr 2
| |->usr3
|
|-> usr4
|->usr6
usr5
|->usr7
The only users that are loaded are usr1, usr2, usr4, usr5, and usr7. usr3 or usr 6 aren't. Im currently trying to recursively force the enclosed users to load with an AfterFind callback:
func (u *User) AfterFind(scope *gorm.Scope, role *CRRole) error {
var childUsers []User
if err := scope.DB().Model(&u).Related(&childUsers, "EnclosedUsers").Error; err != nil {
return err
}
role.EnclosedRoles = childRoles
return nil
}
However this generates the following SQL:
SELECT "users".* FROM "users" INNER JOIN "enclosed_users" ON "enclosed_users"."child_id" = "enclosed_users"."id" WHERE (user_name = 'test user 1') AND ("enclosed_users"."parent_id" IN ('<UUID HERE>'))
if the user_name = ... wasn't there, the query would work perfectly.
Any ideas would be greatly appreciated.
I ended up forking the repository and removing callback_query_preload.go at line 331. Works like a charm.

Resources